mirror of
https://github.com/aljazceru/BTCPayServerPlugins.git
synced 2025-12-16 23:24:25 +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-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}.Debug|Any CPU.ActiveCfg = Altcoins-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.ActiveCfg = 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.Build.0 = Debug|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-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}.Debug|Any CPU.ActiveCfg = Altcoins-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.ActiveCfg = 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.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.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.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.Build.0 = 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 = Debug|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}.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-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}.Debug|Any CPU.ActiveCfg = Altcoins-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.ActiveCfg = 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.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.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.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.Build.0 = 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 = Debug|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}.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-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}.Debug|Any CPU.ActiveCfg = Altcoins-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.ActiveCfg = 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.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.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.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.Build.0 = 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 = 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}.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-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}.Debug|Any CPU.ActiveCfg = Altcoins-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.ActiveCfg = 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.Build.0 = Debug|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">
|
||||
<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/=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_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_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>
|
||||
@@ -50,6 +64,7 @@
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=Nostr/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>
|
||||
@@ -10,7 +10,7 @@
|
||||
<PropertyGroup>
|
||||
<Product>Bitcoin Whitepaper</Product>
|
||||
<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>
|
||||
</PropertyGroup>
|
||||
<!-- Plugin development properties -->
|
||||
|
||||
@@ -7,7 +7,7 @@ namespace BTCPayServer.Plugins.BitcoinWhitepaper
|
||||
{
|
||||
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>
|
||||
<Product>Blink</Product>
|
||||
<Description>Blink Lightning support</Description>
|
||||
<Version>1.0.8</Version>
|
||||
<Version>1.0.9</Version>
|
||||
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
|
||||
<RootNamespace>BTCPayServer.Plugins.Blink</RootNamespace>
|
||||
</PropertyGroup>
|
||||
|
||||
@@ -12,7 +12,7 @@ namespace BTCPayServer.Plugins.Blink
|
||||
{
|
||||
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>
|
||||
<Product>Breez / Greenlight</Product>
|
||||
<Description>Lightweight lightning baby!</Description>
|
||||
<Version>1.0.8</Version>
|
||||
<Version>1.0.9</Version>
|
||||
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
|
||||
</PropertyGroup>
|
||||
<!-- Plugin development properties -->
|
||||
@@ -34,7 +34,7 @@
|
||||
<ProjectReference Include="..\..\submodules\btcpayserver\BTCPayServer\BTCPayServer.csproj" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Breez.Sdk" Version="0.5.2" />
|
||||
<PackageReference Include="Breez.Sdk" Version="0.6.1" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.IO.Compression;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Breez.Sdk;
|
||||
using BTCPayServer.Abstractions.Constants;
|
||||
@@ -12,13 +11,13 @@ using BTCPayServer.Lightning;
|
||||
using BTCPayServer.Models;
|
||||
using BTCPayServer.Payments;
|
||||
using BTCPayServer.Payments.Lightning;
|
||||
using BTCPayServer.Services.Invoices;
|
||||
using BTCPayServer.Services.Stores;
|
||||
using BTCPayServer.Services.Wallets;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using NBitcoin;
|
||||
using NBitcoin.DataEncoders;
|
||||
using NBXplorer.DerivationStrategy;
|
||||
|
||||
namespace BTCPayServer.Plugins.Breez;
|
||||
|
||||
@@ -26,15 +25,19 @@ namespace BTCPayServer.Plugins.Breez;
|
||||
[Route("plugins/{storeId}/Breez")]
|
||||
public class BreezController : Controller
|
||||
{
|
||||
private readonly PaymentMethodHandlerDictionary _paymentMethodHandlerDictionary;
|
||||
private readonly BTCPayNetworkProvider _btcPayNetworkProvider;
|
||||
private readonly BreezService _breezService;
|
||||
private readonly BTCPayWalletProvider _btcWalletProvider;
|
||||
private readonly StoreRepository _storeRepository;
|
||||
|
||||
public BreezController(BTCPayNetworkProvider btcPayNetworkProvider,
|
||||
public BreezController(
|
||||
PaymentMethodHandlerDictionary paymentMethodHandlerDictionary,
|
||||
BTCPayNetworkProvider btcPayNetworkProvider,
|
||||
BreezService breezService,
|
||||
BTCPayWalletProvider btcWalletProvider, StoreRepository storeRepository)
|
||||
{
|
||||
_paymentMethodHandlerDictionary = paymentMethodHandlerDictionary;
|
||||
_btcPayNetworkProvider = btcPayNetworkProvider;
|
||||
_breezService = breezService;
|
||||
_btcWalletProvider = btcWalletProvider;
|
||||
@@ -113,7 +116,7 @@ public class BreezController : Controller
|
||||
if (address.Equals("store", StringComparison.InvariantCultureIgnoreCase))
|
||||
{
|
||||
var store = ControllerContext.HttpContext.GetStoreData()
|
||||
.GetDerivationSchemeSettings(_btcPayNetworkProvider, "BTC");
|
||||
.GetDerivationSchemeSettings(_paymentMethodHandlerDictionary, "BTC");
|
||||
var res = await _btcWalletProvider.GetWallet(storeId)
|
||||
.ReserveAddressAsync(storeId, store.AccountDerivation, "Breez");
|
||||
address = res.Address.ToString();
|
||||
@@ -264,7 +267,7 @@ public class BreezController : Controller
|
||||
if (address.Equals("store", StringComparison.InvariantCultureIgnoreCase))
|
||||
{
|
||||
var store = ControllerContext.HttpContext.GetStoreData()
|
||||
.GetDerivationSchemeSettings(_btcPayNetworkProvider, "BTC");
|
||||
.GetDerivationSchemeSettings(_paymentMethodHandlerDictionary, "BTC");
|
||||
var res = await _btcWalletProvider.GetWallet(storeId)
|
||||
.ReserveAddressAsync(storeId, store.AccountDerivation, "Breez");
|
||||
address = res.Address.ToString();
|
||||
@@ -342,10 +345,8 @@ public class BreezController : Controller
|
||||
public async Task<IActionResult> Configure(string storeId, string command, BreezSettings settings)
|
||||
{
|
||||
var store = HttpContext.GetStoreData();
|
||||
var existing = store.GetSupportedPaymentMethods(_btcPayNetworkProvider).OfType<LightningSupportedPaymentMethod>()
|
||||
.FirstOrDefault(method =>
|
||||
method.PaymentId.PaymentType == LightningPaymentType.Instance &&
|
||||
method.PaymentId.CryptoCode == "BTC");
|
||||
var pmi = PaymentTypes.LN.GetPaymentMethodId("BTC");
|
||||
var existing = store.GetPaymentMethodConfig<LightningPaymentMethodConfig>(pmi, _paymentMethodHandlerDictionary);
|
||||
|
||||
if (command == "clear")
|
||||
{
|
||||
@@ -355,7 +356,7 @@ public class BreezController : Controller
|
||||
var isStoreSetToThisMicro = existing?.GetExternalLightningUrl() == client?.ToString();
|
||||
if (client is not null && isStoreSetToThisMicro)
|
||||
{
|
||||
store.SetSupportedPaymentMethod(existing.PaymentId, null);
|
||||
store.SetPaymentMethodConfig(_paymentMethodHandlerDictionary[pmi], null);
|
||||
await _storeRepository.UpdateStore(store);
|
||||
}
|
||||
return RedirectToAction(nameof(Configure), new {storeId});
|
||||
@@ -422,18 +423,13 @@ public class BreezController : Controller
|
||||
|
||||
if(existing is null)
|
||||
{
|
||||
existing = new LightningSupportedPaymentMethod()
|
||||
{
|
||||
CryptoCode = "BTC"
|
||||
};
|
||||
|
||||
existing = new LightningPaymentMethodConfig();
|
||||
var client = _breezService.GetClient(storeId);
|
||||
existing.SetLightningUrl(client);
|
||||
store.SetSupportedPaymentMethod(existing);
|
||||
var lnurl = new LNURLPaySupportedPaymentMethod()
|
||||
{
|
||||
CryptoCode = "BTC",
|
||||
};
|
||||
store.SetSupportedPaymentMethod(lnurl);
|
||||
store.SetPaymentMethodConfig(_paymentMethodHandlerDictionary[pmi], existing);
|
||||
var lnurlPMI = PaymentTypes.LNURL.GetPaymentMethodId("BTC");
|
||||
store.SetPaymentMethodConfig(_paymentMethodHandlerDictionary[lnurlPMI], new LNURLPaymentMethodConfig());
|
||||
await _storeRepository.UpdateStore(store);
|
||||
}
|
||||
|
||||
|
||||
@@ -252,7 +252,7 @@ public class BreezLightningClient : ILightningClient, IDisposable, EventListener
|
||||
OffchainBalance = new OffchainBalance()
|
||||
{
|
||||
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
|
||||
{
|
||||
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;
|
||||
|
||||
@@ -12,7 +12,7 @@ namespace BTCPayServer.Plugins.Breez
|
||||
{
|
||||
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)
|
||||
|
||||
@@ -11,7 +11,9 @@ using BTCPayServer.Events;
|
||||
using BTCPayServer.HostedServices;
|
||||
using BTCPayServer.Payments;
|
||||
using BTCPayServer.Payments.Lightning;
|
||||
using BTCPayServer.Services.Invoices;
|
||||
using BTCPayServer.Services.Stores;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Options;
|
||||
using NBitcoin;
|
||||
@@ -22,7 +24,8 @@ public class BreezService:EventHostedServiceBase
|
||||
{
|
||||
private readonly StoreRepository _storeRepository;
|
||||
private readonly IOptions<DataDirectories> _dataDirectories;
|
||||
private readonly BTCPayNetworkProvider _btcPayNetworkProvider;
|
||||
private readonly IServiceProvider _serviceProvider;
|
||||
private PaymentMethodHandlerDictionary _paymentMethodHandlerDictionary => _serviceProvider.GetRequiredService<PaymentMethodHandlerDictionary>();
|
||||
private readonly ILogger _logger;
|
||||
private Dictionary<string, BreezSettings> _settings;
|
||||
private Dictionary<string, BreezLightningClient> _clients = new();
|
||||
@@ -31,12 +34,12 @@ public class BreezService:EventHostedServiceBase
|
||||
EventAggregator eventAggregator,
|
||||
StoreRepository storeRepository,
|
||||
IOptions<DataDirectories> dataDirectories,
|
||||
BTCPayNetworkProvider btcPayNetworkProvider,
|
||||
IServiceProvider serviceProvider,
|
||||
ILogger<BreezService> logger) : base(eventAggregator, logger)
|
||||
{
|
||||
_storeRepository = storeRepository;
|
||||
_dataDirectories = dataDirectories;
|
||||
_btcPayNetworkProvider = btcPayNetworkProvider;
|
||||
_serviceProvider = serviceProvider;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
@@ -133,13 +136,13 @@ public class BreezService:EventHostedServiceBase
|
||||
{
|
||||
_settings.Remove(storeId, out var oldSettings );
|
||||
var data = await _storeRepository.FindStore(storeId);
|
||||
var existing = data?.GetSupportedPaymentMethods(_btcPayNetworkProvider)
|
||||
.OfType<LightningSupportedPaymentMethod>().FirstOrDefault(method =>
|
||||
method.CryptoCode == "BTC" && method.PaymentId.PaymentType == LightningPaymentType.Instance);
|
||||
var pmi = PaymentTypes.LN.GetPaymentMethodId("BTC");
|
||||
var existing =
|
||||
data?.GetPaymentMethodConfig<LightningPaymentMethodConfig>(pmi, _paymentMethodHandlerDictionary);
|
||||
var isBreez = existing?.GetExternalLightningUrl() == $"type=breez;key={oldSettings.PaymentKey}";
|
||||
if (isBreez)
|
||||
{
|
||||
data.SetSupportedPaymentMethod(new PaymentMethodId("BTC", LightningPaymentType.Instance), null );
|
||||
data.SetPaymentMethodConfig(_paymentMethodHandlerDictionary[pmi], null );
|
||||
await _storeRepository.UpdateStore(data);
|
||||
}
|
||||
Directory.Delete(GetWorkDir(storeId), true);
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
@using Breez.Sdk
|
||||
@using BTCPayServer
|
||||
@using BTCPayServer.Abstractions.Extensions
|
||||
@using BTCPayServer.Abstractions.Contracts
|
||||
@using BTCPayServer.Client
|
||||
@using BTCPayServer.Components.QRCode
|
||||
@using BTCPayServer.Components.TruncateCenter
|
||||
@@ -10,13 +8,15 @@
|
||||
@using BTCPayServer.Plugins.Breez
|
||||
@using BTCPayServer.Security
|
||||
@using BTCPayServer.Services
|
||||
@using BTCPayServer.Services.Invoices
|
||||
@using Microsoft.AspNetCore.Mvc.TagHelpers
|
||||
@using NBitcoin
|
||||
@inject BreezService BreezService
|
||||
@inject BTCPayNetworkProvider BtcPayNetworkProvider
|
||||
@inject TransactionLinkProviders TransactionLinkProviders
|
||||
@inject PaymentMethodHandlerDictionary PaymentMethodHandlerDictionary
|
||||
@{
|
||||
ViewData.SetActivePage("Breez", "Swap In", "SwapIn");
|
||||
var pmi = PaymentTypes.CHAIN.GetPaymentMethodId("BTC");
|
||||
string storeId = Model switch
|
||||
{
|
||||
string s => s,
|
||||
@@ -38,10 +38,9 @@
|
||||
}
|
||||
|
||||
var refundables = sdk.ListRefundables();
|
||||
var deriv = Context.GetStoreData().GetDerivationSchemeSettings(BtcPayNetworkProvider, "BTC");
|
||||
var deriv = Context.GetStoreData().GetDerivationSchemeSettings(PaymentMethodHandlerDictionary, "BTC");
|
||||
var ni = sdk.NodeInfo();
|
||||
var f = sdk.RecommendedFees();
|
||||
var pmi = new PaymentMethodId("BTC", PaymentTypes.BTCLike);
|
||||
}
|
||||
|
||||
<datalist id="fees">
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
@using BTCPayServer
|
||||
@using BTCPayServer.Abstractions.Extensions
|
||||
@using BTCPayServer.Plugins.Breez
|
||||
@using BTCPayServer.Security
|
||||
@using BTCPayServer.Services.Invoices
|
||||
@using Microsoft.AspNetCore.Mvc.TagHelpers
|
||||
@using Microsoft.AspNetCore.Routing
|
||||
@model string
|
||||
@inject BreezService BreezService
|
||||
@inject BTCPayNetworkProvider BtcPayNetworkProvider
|
||||
@inject PaymentMethodHandlerDictionary PaymentMethodHandlerDictionary
|
||||
@{
|
||||
var storeId = Context.GetImplicitStoreId();
|
||||
var address = Context.GetRouteValue("address").ToString();
|
||||
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 f = sdk.RecommendedFees();
|
||||
}
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
@using Breez.Sdk
|
||||
@using BTCPayServer
|
||||
@using BTCPayServer.Abstractions.Extensions
|
||||
@using BTCPayServer.Models.StoreViewModels
|
||||
@using BTCPayServer.Plugins.Breez
|
||||
@using BTCPayServer.Security
|
||||
@using BTCPayServer.Services.Invoices
|
||||
@using Microsoft.AspNetCore.Mvc.TagHelpers
|
||||
@inject BreezService BreezService
|
||||
@inject BTCPayNetworkProvider BtcPayNetworkProvider
|
||||
@inject PaymentMethodHandlerDictionary PaymentMethodHandlerDictionary
|
||||
|
||||
|
||||
@{
|
||||
@@ -29,7 +30,7 @@
|
||||
if (sdk is null)
|
||||
return;
|
||||
var inProgressSwaps = sdk.InProgressReverseSwaps();
|
||||
var deriv = Context.GetStoreData().GetDerivationSchemeSettings(BtcPayNetworkProvider, "BTC");
|
||||
var deriv = Context.GetStoreData().GetDerivationSchemeSettings(PaymentMethodHandlerDictionary, "BTC");
|
||||
var f = sdk.RecommendedFees();
|
||||
var swapOutRec = sdk.FetchReverseSwapFees(new ReverseSwapFeesRequest());
|
||||
}
|
||||
|
||||
@@ -2,9 +2,10 @@
|
||||
@using BTCPayServer.Models.StoreViewModels
|
||||
@using BTCPayServer.Plugins.Breez
|
||||
@using BTCPayServer.Security
|
||||
@using BTCPayServer.Services.Invoices
|
||||
@using Microsoft.AspNetCore.Mvc.TagHelpers
|
||||
@inject BreezService BreezService
|
||||
@inject BTCPayNetworkProvider BtcPayNetworkProvider
|
||||
@inject PaymentMethodHandlerDictionary PaymentMethodHandlerDictionary
|
||||
@{
|
||||
Layout = "_Layout";
|
||||
ViewData.SetActivePage("Breez", "Sweep", "Sweep");
|
||||
@@ -24,7 +25,7 @@
|
||||
var sdk = BreezService.GetClient(storeId)?.Sdk;
|
||||
if (sdk is null)
|
||||
return;
|
||||
var deriv = Context.GetStoreData().GetDerivationSchemeSettings(BtcPayNetworkProvider, "BTC");
|
||||
var deriv = Context.GetStoreData().GetDerivationSchemeSettings(PaymentMethodHandlerDictionary, "BTC");
|
||||
var f = sdk.RecommendedFees();
|
||||
}
|
||||
<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,17 +1,30 @@
|
||||
@using Breez.Sdk
|
||||
@using BTCPayServer.Abstractions.Contracts
|
||||
@using BTCPayServer.Abstractions.Extensions
|
||||
@using BTCPayServer.Client
|
||||
@using BTCPayServer.Models.StoreViewModels
|
||||
@using BTCPayServer.Plugins.Breez
|
||||
@using BTCPayServer.Security
|
||||
@using Microsoft.AspNetCore.Mvc.TagHelpers
|
||||
@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))
|
||||
{
|
||||
<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="Group" transform="translate(3.000000, 2.000000)" fill-rule="nonzero">
|
||||
<path d="M35.4723926,39.8214286 C35.4723926,37.9541367 33.9340883,36.4285714 32.0236136,36.4285714 L10.3260796,36.4285714 C8.42801059,36.4285714 6.87730061,37.9419322 6.87730061,39.8214286 C6.87730061,41.6887205 8.41560491,43.2142857 10.3260796,43.2142857 L32.0236136,43.2142857 C33.9216827,43.2020812 35.4723926,41.6887205 35.4723926,39.8214286 Z" id="Shape" fill="currentColor"></path>
|
||||
@@ -20,8 +33,35 @@
|
||||
<path d="M15.7746737,21.4285714 L31.280541,21.4285714 C33.1891473,21.4285714 34.7484663,19.9152107 34.7484663,18.0357143 C34.7484663,16.1684224 33.2016219,14.6428571 31.280541,14.6428571 L15.7746737,14.6428571 C13.8660674,14.6428571 12.3067485,16.1562179 12.3067485,18.0357143 C12.3067485,19.9030062 13.8535928,21.4285714 15.7746737,21.4285714 Z" id="Shape" fill="currentColor"></path>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
</svg>
|
||||
<span>Breez</span>
|
||||
</a>
|
||||
</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>
|
||||
</div>
|
||||
<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>
|
||||
</div>
|
||||
<div class="balance d-flex align-items-baseline gap-1">
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
<PropertyGroup>
|
||||
<Product>Bringin</Product>
|
||||
<Description>Euro Offramp</Description>
|
||||
<Version>1.0.1</Version>
|
||||
<Version>1.0.2</Version>
|
||||
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
|
||||
</PropertyGroup>
|
||||
<!-- Plugin development properties -->
|
||||
@@ -41,6 +41,6 @@
|
||||
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="AsyncKeyedLock" Version="6.3.4" />
|
||||
<PackageReference Include="AsyncKeyedLock" Version="7.0.1" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
||||
@@ -11,7 +11,10 @@ public class BringinPlugin : BaseBTCPayServerPlugin
|
||||
{
|
||||
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)
|
||||
|
||||
@@ -17,6 +17,7 @@ using BTCPayServer.Events;
|
||||
using BTCPayServer.HostedServices;
|
||||
using BTCPayServer.Lightning;
|
||||
using BTCPayServer.Payments;
|
||||
using BTCPayServer.Payouts;
|
||||
using BTCPayServer.Services;
|
||||
using BTCPayServer.Services.Stores;
|
||||
using Microsoft.Extensions.Logging;
|
||||
@@ -139,13 +140,15 @@ public class BringinService : EventHostedServiceBase
|
||||
invoiceEvent when bringinStoreSettings.Enabled:
|
||||
|
||||
var pmPayments = invoiceEvent.Invoice.GetPayments("BTC", true)
|
||||
.GroupBy(payment => payment.GetPaymentMethodId());
|
||||
.GroupBy(payment => payment.PaymentMethodId);
|
||||
var update = false;
|
||||
foreach (var pmPayment in pmPayments)
|
||||
{
|
||||
var methodId = pmPayment.Key;
|
||||
if (methodId.PaymentType == PaymentTypes.LNURLPay)
|
||||
methodId = new PaymentMethodId(methodId.CryptoCode, PaymentTypes.LightningLike);
|
||||
if (methodId == PaymentTypes.LNURL.GetPaymentMethodId("BTC"))
|
||||
{
|
||||
methodId = PaymentTypes.LN.GetPaymentMethodId("BTC");
|
||||
}
|
||||
if (!bringinStoreSettings.MethodSettings.TryGetValue(methodId.ToString(),
|
||||
out var methodSettings))
|
||||
{
|
||||
@@ -153,7 +156,7 @@ public class BringinService : EventHostedServiceBase
|
||||
}
|
||||
|
||||
methodSettings.CurrentBalance +=
|
||||
pmPayment.Sum(payment => payment.GetCryptoPaymentData().GetValue());
|
||||
pmPayment.Sum(payment => payment.Value);
|
||||
update = true;
|
||||
}
|
||||
|
||||
@@ -190,14 +193,14 @@ public class BringinService : EventHostedServiceBase
|
||||
|
||||
foreach (var methodSetting in bringinStoreSetting.MethodSettings)
|
||||
{
|
||||
var pmi = PaymentMethodId.TryParse(methodSetting.Key);
|
||||
var pmi = PayoutMethodId.TryParse(methodSetting.Key);
|
||||
if (pmi is null)
|
||||
{
|
||||
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 (methodSetting.Value.PendingPayouts.Count > 0 && pmi.PaymentType == BitcoinPaymentType.Instance)
|
||||
if (methodSetting.Value.PendingPayouts.Count > 0 && isOnChain)
|
||||
{
|
||||
var cancelResult = await _pullPaymentHostedService.Cancel(
|
||||
new PullPaymentHostedService.CancelRequest(methodSetting.Value.PendingPayouts.ToArray(),
|
||||
@@ -252,16 +255,16 @@ public class BringinService : EventHostedServiceBase
|
||||
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 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);
|
||||
@@ -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
|
||||
if (supportedMethod.FiatMinimumAmount > 0)
|
||||
{
|
||||
@@ -297,13 +300,13 @@ public class BringinService : EventHostedServiceBase
|
||||
{
|
||||
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)):
|
||||
new AddressClaimDestination(BitcoinAddress.Create(order.DepositAddress, network.NBitcoinNetwork));
|
||||
var claim = await _pullPaymentHostedService.Claim(new ClaimRequest()
|
||||
{
|
||||
PaymentMethodId = paymentMethodId,
|
||||
PayoutMethodId = paymentMethodId,
|
||||
StoreId = storeId,
|
||||
Destination = destination,
|
||||
Value = orderMoney.ToUnit(MoneyUnit.BTC),
|
||||
@@ -363,17 +366,17 @@ public class BringinService : EventHostedServiceBase
|
||||
{
|
||||
case PayoutState.Completed:
|
||||
// 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);
|
||||
case PayoutState.Cancelled:
|
||||
// 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);
|
||||
var pmi = payout.GetPaymentMethodId();
|
||||
var pmi = payout.GetPayoutMethodId();
|
||||
if (_settings[payout.StoreDataId].MethodSettings
|
||||
.TryGetValue(pmi.ToString(), out var methodSettings))
|
||||
{
|
||||
methodSettings.CurrentBalance += payout.GetBlob(_btcPayNetworkJsonSerializerSettings).Amount;
|
||||
methodSettings.CurrentBalance += payout.Amount ?? payout.OriginalAmount;
|
||||
result = true;
|
||||
}
|
||||
|
||||
@@ -389,12 +392,12 @@ public class BringinService : EventHostedServiceBase
|
||||
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[]
|
||||
{
|
||||
new SupportedMethodOptions(new PaymentMethodId("BTC", LightningPaymentType.Instance), true, 22, "LIGHTNING"),
|
||||
new SupportedMethodOptions(new PaymentMethodId("BTC", BitcoinPaymentType.Instance), true, 22, "ON_CHAIN"),
|
||||
new SupportedMethodOptions(PayoutTypes.LN.GetPayoutMethodId("BTC"), true, 22, "LIGHTNING"),
|
||||
new SupportedMethodOptions(PayoutTypes.CHAIN.GetPayoutMethodId("BTC"), true, 22, "ON_CHAIN"),
|
||||
};
|
||||
|
||||
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
|
||||
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()
|
||||
{
|
||||
FiatThreshold = supportedMethod.FiatMinimum,
|
||||
@@ -424,7 +427,7 @@ public class BringinService : EventHostedServiceBase
|
||||
}
|
||||
|
||||
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);
|
||||
isNew = true;
|
||||
return (storeLock, result, DateTimeOffset.Now.AddMinutes(5));
|
||||
|
||||
@@ -4,7 +4,9 @@
|
||||
@using BTCPayServer.Data
|
||||
@using BTCPayServer.Payments
|
||||
@using BTCPayServer.PayoutProcessors
|
||||
@using BTCPayServer.Payouts
|
||||
@using BTCPayServer.Services
|
||||
@using BTCPayServer.Services.Invoices
|
||||
@using BTCPayServer.Services.Stores
|
||||
@using Microsoft.AspNetCore.Http
|
||||
@using Microsoft.AspNetCore.Routing
|
||||
@@ -25,6 +27,7 @@
|
||||
[Inject] private IHttpClientFactory HttpClientFactory { get; set; }
|
||||
[Inject] private PayoutProcessorService PayoutProcessorService { get; set; }
|
||||
[Inject] private IAuthorizationService AuthorizationService { get; set; }
|
||||
[Inject] private PayoutMethodHandlerDictionary PayoutMethodHandlerDictionary { get; set; }
|
||||
[Parameter] public string StoreId { get; set; }
|
||||
private decimal? LastFiatBalance { 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>";
|
||||
_callbackLink = LinkGenerator.GetUriByAction(HttpContextAccessor.HttpContext, "Callback", "Bringin", new {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()
|
||||
{
|
||||
Stores = new[] {StoreId},
|
||||
PaymentMethods = _pms.Select(p => p.ToString()).ToArray()
|
||||
})).Select(data => PaymentMethodId.TryParse(data.PaymentMethod)).Where(id => id is not null).ToArray();
|
||||
PayoutMethods = _pms.Select(p => p).ToArray()
|
||||
})).Select(data => PayoutMethodId.TryParse(data.PayoutMethodId)).Where(id => id is not null).ToArray();
|
||||
EditMode = BringinService.IsInEditMode(StoreId);
|
||||
IsLoaded = true;
|
||||
_ = FetchBalanceAndRate();
|
||||
@@ -148,8 +152,8 @@
|
||||
}
|
||||
|
||||
private bool _saving;
|
||||
private PaymentMethodId[] _pms;
|
||||
private PaymentMethodId[] _pps;
|
||||
private HashSet<PayoutMethodId> _pms;
|
||||
private PayoutMethodId[] _pps;
|
||||
private bool _apiKeyError;
|
||||
|
||||
private async Task Save()
|
||||
@@ -269,7 +273,7 @@
|
||||
_saving = true;
|
||||
|
||||
await InvokeAsync(StateHasChanged);
|
||||
var pm = PaymentMethodId.TryParse(ManualOrderPaymentMethod);
|
||||
var pm = PayoutMethodId.TryParse(ManualOrderPaymentMethod);
|
||||
if (pm is null)
|
||||
{
|
||||
SaveError = "Invalid payment method";
|
||||
@@ -391,8 +395,8 @@
|
||||
}
|
||||
else if (_manualOrder)
|
||||
{
|
||||
var items = new List<PaymentMethodId>();
|
||||
items.AddRange(BringinService.SupportedMethods.Where(s => _pms.Contains(s.PaymentMethod)).Select(s => s.PaymentMethod));
|
||||
var items = new List<PayoutMethodId>();
|
||||
items.AddRange(BringinService.SupportedMethods.Where(s => _pms.Contains(s.PayoutMethod)).Select(s => s.PayoutMethod));
|
||||
|
||||
|
||||
<div class="row">
|
||||
@@ -422,7 +426,7 @@
|
||||
<option value="">Select a payment method</option>
|
||||
@foreach (var opt in items)
|
||||
{
|
||||
<option value="@opt.ToString()">@opt.ToPrettyString()</option>
|
||||
<option value="@opt.ToString()">@opt</option>
|
||||
}
|
||||
</select>
|
||||
</div>
|
||||
@@ -472,7 +476,7 @@
|
||||
|
||||
@foreach (var method in _settings.MethodSettings)
|
||||
{
|
||||
var pmi = PaymentMethodId.TryParse(method.Key);
|
||||
var pmi = PayoutMethodId.TryParse(method.Key);
|
||||
if (pmi is null)
|
||||
continue;
|
||||
if (!_pms.Contains(pmi))
|
||||
@@ -480,7 +484,7 @@
|
||||
<hr class=""/>
|
||||
<div class="store-number">
|
||||
<header>
|
||||
<h6>@pmi.ToPrettyString()</h6>
|
||||
<h6>@pmi</h6>
|
||||
</header>
|
||||
|
||||
@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>
|
||||
@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
|
||||
}
|
||||
</div>
|
||||
@@ -579,9 +583,9 @@
|
||||
var pmId = PaymentMethodId.TryParse(method.Key);
|
||||
if (pmId is null)
|
||||
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" : "")}" : "")">
|
||||
<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="form-group">
|
||||
<label class="form-label">Percentage</label>
|
||||
@@ -644,15 +648,16 @@
|
||||
<tr>
|
||||
<td>@tx.CreatedAt.ToTimeAgo()</td>
|
||||
<td>@tx.SubType.ToHumanReadable()</td>
|
||||
<td>
|
||||
@tx.Status.ToHumanReadable()
|
||||
</td>
|
||||
<td>@tx.Status.ToHumanReadable()</td>
|
||||
<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>
|
||||
</tr>
|
||||
}
|
||||
</tbody>
|
||||
</tbody>s
|
||||
</table>
|
||||
</div>
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
<PropertyGroup>
|
||||
<Product>Data Erasure</Product>
|
||||
<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>
|
||||
</PropertyGroup>
|
||||
<!-- Plugin development properties -->
|
||||
|
||||
@@ -12,6 +12,7 @@ namespace BTCPayServer.Plugins.DataErasure
|
||||
public class DataErasureController : Controller
|
||||
{
|
||||
private readonly DataErasureService _dataErasureService;
|
||||
|
||||
public DataErasureController(DataErasureService dataErasureService)
|
||||
{
|
||||
_dataErasureService = dataErasureService;
|
||||
@@ -31,7 +32,8 @@ namespace BTCPayServer.Plugins.DataErasure
|
||||
{
|
||||
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)
|
||||
{
|
||||
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":
|
||||
await _dataErasureService.Set(storeId, vm);
|
||||
TempData["SuccessMessage"] = "Data erasure settings modified";
|
||||
|
||||
@@ -9,7 +9,7 @@ namespace BTCPayServer.Plugins.DataErasure
|
||||
{
|
||||
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)
|
||||
{
|
||||
|
||||
@@ -3,6 +3,7 @@ using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using BTCPayServer.Abstractions.Contracts;
|
||||
using BTCPayServer.Data;
|
||||
using BTCPayServer.Services.Invoices;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using Microsoft.Extensions.Logging;
|
||||
@@ -14,13 +15,15 @@ namespace BTCPayServer.Plugins.DataErasure
|
||||
private readonly IStoreRepository _storeRepository;
|
||||
private readonly ILogger<DataErasureService> _logger;
|
||||
private readonly InvoiceRepository _invoiceRepository;
|
||||
private readonly ApplicationDbContextFactory _dbContextFactory;
|
||||
|
||||
public DataErasureService(IStoreRepository storeRepository, ILogger<DataErasureService> logger,
|
||||
InvoiceRepository invoiceRepository)
|
||||
InvoiceRepository invoiceRepository, ApplicationDbContextFactory dbContextFactory)
|
||||
{
|
||||
_storeRepository = storeRepository;
|
||||
_logger = logger;
|
||||
_invoiceRepository = invoiceRepository;
|
||||
_dbContextFactory = dbContextFactory;
|
||||
}
|
||||
|
||||
public async Task<DataErasureSettings> Get(string storeId)
|
||||
@@ -29,13 +32,16 @@ namespace BTCPayServer.Plugins.DataErasure
|
||||
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();
|
||||
var existing = await Get(storeId);
|
||||
settings.LastRunCutoff = existing?.LastRunCutoff;
|
||||
settings.LastRunCutoff = clearDate? null: existing?.LastRunCutoff;
|
||||
await SetCore(storeId, settings);
|
||||
_runningLock.Release();
|
||||
_cts = new CancellationTokenSource();
|
||||
_ = Run();
|
||||
}
|
||||
|
||||
private async Task SetCore(string storeId, DataErasureSettings settings)
|
||||
@@ -46,11 +52,11 @@ namespace BTCPayServer.Plugins.DataErasure
|
||||
public bool IsRunning { get; private set; }
|
||||
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;
|
||||
|
||||
|
||||
@@ -58,9 +64,20 @@ namespace BTCPayServer.Plugins.DataErasure
|
||||
await _storeRepository.GetSettingsAsync<DataErasureSettings>(nameof(DataErasureSettings));
|
||||
foreach (var setting in settings.Where(setting => setting.Value.Enabled))
|
||||
{
|
||||
var skip = 0;
|
||||
var count = 0;
|
||||
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)
|
||||
{
|
||||
var invoices = await _invoiceRepository.GetInvoices(new InvoiceQuery()
|
||||
@@ -70,7 +87,10 @@ namespace BTCPayServer.Plugins.DataErasure
|
||||
StoreId = new[] {setting.Key},
|
||||
Skip = skip,
|
||||
Take = 100
|
||||
});
|
||||
}, _cts.Token);
|
||||
|
||||
|
||||
|
||||
foreach (var invoice in invoices)
|
||||
{
|
||||
//replace all buyer info with "erased"
|
||||
@@ -104,7 +124,9 @@ namespace BTCPayServer.Plugins.DataErasure
|
||||
|
||||
skip += 100;
|
||||
}
|
||||
if(count > 0)
|
||||
}
|
||||
|
||||
if (count > 0)
|
||||
_logger.LogInformation($"Erased {count} invoice data for store {setting.Key}");
|
||||
setting.Value.LastRunCutoff = cutoffDate;
|
||||
await SetCore(setting.Key, setting.Value);
|
||||
@@ -114,18 +136,30 @@ namespace BTCPayServer.Plugins.DataErasure
|
||||
|
||||
|
||||
_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)
|
||||
{
|
||||
_ = Run(cancellationToken);
|
||||
_cts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken);
|
||||
_ = Run();
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public Task StopAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
_cts?.Cancel();
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,5 +7,7 @@ namespace BTCPayServer.Plugins.DataErasure
|
||||
public bool Enabled { get; set; }
|
||||
public int DaysToKeep { 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"/>
|
||||
|
||||
</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)
|
||||
{
|
||||
<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>
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
<PropertyGroup>
|
||||
<Product>Dynamic Rate Limit</Product>
|
||||
<Description>Allows you to override the default rate limiting.</Description>
|
||||
<Version>1.0.1</Version>
|
||||
<Version>1.0.2</Version>
|
||||
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
|
||||
</PropertyGroup>
|
||||
<!-- Plugin development properties -->
|
||||
|
||||
@@ -10,7 +10,7 @@ public class DynamicRateLimitsPlugin : BaseBTCPayServerPlugin
|
||||
{
|
||||
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)
|
||||
{
|
||||
|
||||
@@ -1,11 +1,6 @@
|
||||
@using BTCPayServer.Plugins.DynamicRateLimits
|
||||
@model DynamicRateLimitSettings
|
||||
|
||||
@{
|
||||
Layout = "../Shared/_NavLayout.cshtml";
|
||||
ViewData["NavPartialName"] = "../UIServer/_Nav";
|
||||
}
|
||||
|
||||
<h2 class="mb-4">Rate limit configuration</h2>
|
||||
|
||||
<form method="post">
|
||||
|
||||
@@ -1,7 +1,13 @@
|
||||
@using BTCPayServer.Client
|
||||
@using BTCPayServer.Plugins.DynamicRateLimits
|
||||
@using Microsoft.AspNetCore.Mvc.TagHelpers
|
||||
@{
|
||||
var isActive = ViewContext.RouteData.Values.TryGetValue("Controller", out var controller) && controller is not null &&
|
||||
nameof(DynamicRatesLimiterController).StartsWith(controller?.ToString(), StringComparison.InvariantCultureIgnoreCase);
|
||||
}
|
||||
|
||||
<a class="nav-link @(isActive ? "active" : string.Empty)" asp-action="Update" asp-controller="DynamicRatesLimiter">Rate Limits</a>
|
||||
|
||||
<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>
|
||||
</li>
|
||||
@@ -9,7 +9,7 @@
|
||||
<PropertyGroup>
|
||||
<Product>Dynamic Reports</Product>
|
||||
<Description>Allows you to create custom reports using SQL.</Description>
|
||||
<Version>1.0.1</Version>
|
||||
<Version>1.0.2</Version>
|
||||
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
|
||||
</PropertyGroup>
|
||||
<!-- Plugin development properties -->
|
||||
|
||||
@@ -10,7 +10,7 @@ public class DynamicReportsPlugin : BaseBTCPayServerPlugin
|
||||
{
|
||||
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)
|
||||
{
|
||||
|
||||
@@ -21,19 +21,15 @@ public class PostgresReportProvider : ReportProvider
|
||||
public DynamicReportsSettings.DynamicReportSetting Setting { get; set; }
|
||||
|
||||
private readonly ApplicationDbContextFactory _dbContextFactory;
|
||||
private readonly IOptions<DatabaseOptions> _options;
|
||||
private readonly IHttpContextAccessor _httpContextAccessor;
|
||||
public PostgresReportProvider( ApplicationDbContextFactory dbContextFactory,
|
||||
IOptions<DatabaseOptions> options, IHttpContextAccessor httpContextAccessor)
|
||||
public PostgresReportProvider( ApplicationDbContextFactory dbContextFactory, IHttpContextAccessor httpContextAccessor)
|
||||
{
|
||||
_dbContextFactory = dbContextFactory;
|
||||
_options = options;
|
||||
_httpContextAccessor = httpContextAccessor;
|
||||
}
|
||||
public override bool IsAvailable()
|
||||
{
|
||||
return _options.Value.DatabaseType == DatabaseType.Postgres &&
|
||||
Setting.AllowForNonAdmins || _httpContextAccessor.HttpContext?.User.IsInRole(Roles.ServerAdmin) is true;
|
||||
return Setting.AllowForNonAdmins || _httpContextAccessor.HttpContext?.User.IsInRole(Roles.ServerAdmin) is true;
|
||||
}
|
||||
public override async Task Query(QueryContext queryContext, CancellationToken cancellation)
|
||||
{
|
||||
|
||||
@@ -10,8 +10,6 @@
|
||||
@inject DynamicReportService DynamicReportService
|
||||
|
||||
@{
|
||||
Layout = "../Shared/_NavLayout.cshtml";
|
||||
ViewData["NavPartialName"] = "../UIServer/_Nav";
|
||||
var storeId = ScopeProvider.GetCurrentStoreId();
|
||||
var reportName = Context.Request.Query["reportName"].ToString();
|
||||
reportName = string.IsNullOrEmpty(reportName) ? null : reportName;
|
||||
|
||||
@@ -1,8 +1,15 @@
|
||||
@using BTCPayServer.Client
|
||||
@using BTCPayServer.Plugins.DynamicReports
|
||||
@using Microsoft.AspNetCore.Mvc.TagHelpers
|
||||
|
||||
@{
|
||||
var isActive = ViewContext.RouteData.Values.TryGetValue("Controller", out var controller) && controller is not null &&
|
||||
nameof(DynamicReportsController).StartsWith(controller?.ToString(), StringComparison.InvariantCultureIgnoreCase);
|
||||
}
|
||||
|
||||
<a class="nav-link @(isActive ? "active" : string.Empty)" asp-action="Update" asp-controller="DynamicReports">Dynamic Reports</a>
|
||||
|
||||
<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>
|
||||
</li>
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
<PropertyGroup>
|
||||
<Product>File Seller</Product>
|
||||
<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>
|
||||
</PropertyGroup>
|
||||
<!-- Plugin development properties -->
|
||||
|
||||
@@ -9,8 +9,9 @@ public class FileSellerPlugin : BaseBTCPayServerPlugin
|
||||
{
|
||||
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)
|
||||
{
|
||||
applicationBuilder.AddHostedService<FileSellerService>();
|
||||
|
||||
@@ -6,16 +6,16 @@
|
||||
@inject UserManager<ApplicationUser> UserManager
|
||||
@inject UserService UserService
|
||||
@{
|
||||
var userId = UserManager.GetUserId(User);
|
||||
var user = await UserManager.GetUserAsync(User);
|
||||
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", ""));
|
||||
}
|
||||
<template v-if="editingItem">
|
||||
<div class="form-group">
|
||||
<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>
|
||||
</div>
|
||||
</template>
|
||||
@@ -9,7 +9,7 @@
|
||||
<PropertyGroup>
|
||||
<Product>FixedFloat</Product>
|
||||
<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>
|
||||
</PropertyGroup>
|
||||
<!-- Plugin development properties -->
|
||||
|
||||
@@ -9,29 +9,16 @@ namespace BTCPayServer.Plugins.FixedFloat
|
||||
{
|
||||
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)
|
||||
{
|
||||
applicationBuilder.AddSingleton<FixedFloatService>();
|
||||
applicationBuilder.AddSingleton<IUIExtension>(new UIExtension("FixedFloat/FixedFloatNav",
|
||||
"store-integrations-nav"));
|
||||
// Checkout v2
|
||||
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"));
|
||||
applicationBuilder.AddUIExtension("store-integrations-nav", "FixedFloat/FixedFloatNav");
|
||||
applicationBuilder.AddUIExtension("checkout-payment-method", "FixedFloat/CheckoutPaymentMethodExtension");
|
||||
applicationBuilder.AddUIExtension("checkout-payment", "FixedFloat/CheckoutPaymentExtension");
|
||||
|
||||
base.Execute(applicationBuilder);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,47 +20,61 @@ namespace BTCPayServer.Plugins.FixedFloat
|
||||
{
|
||||
{"AAVEETH", "Aave (ERC20)"},
|
||||
{"ADA", "Cardano"},
|
||||
{"ADABSC", "Cardano (BEP20)"},
|
||||
{"APT", "Aptos"},
|
||||
{"ATOM", "Cosmos"},
|
||||
{"AVAX", "Avalanche (C-Chain)"},
|
||||
{"BAT", "Basic Attention (ERC20)"},
|
||||
{"BCH", "Bitcoin Cash"},
|
||||
{"BNB", "BNB Beacon Chain (BEP2)"},
|
||||
{"BSC", "BNB Smart Chain (BEP20)"},
|
||||
{"WBNBBSC", "Wrapped BNB (BEP20)"},
|
||||
{"BTC", "Bitcoin"},
|
||||
{"BTCBSC", "Bitcoin (BEP20)"},
|
||||
{"BTCLN", "Bitcoin (Lightning)"},
|
||||
{"BTT", "BitTorrent"},
|
||||
{"BUSD", "Binance USD (BEP2)"},
|
||||
{"BUSDBSC", "Binance USD (BEP20)"},
|
||||
{"BUSDETH", "Binance USD (ERC20)"},
|
||||
{"CAKE", "PancakeSwap (BEP20)"},
|
||||
{"DAIBSC", "DAI (BEP20)"},
|
||||
{"DAIETH", "DAI (ERC20)"},
|
||||
{"DAIMATIC", "DAI (Polygon)"},
|
||||
{"DASH", "Dash"},
|
||||
{"DOGE", "Dogecoin"},
|
||||
{"DOT", "Polkadot"},
|
||||
{"EOS", "EOS"},
|
||||
{"ETC", "Ethereum Classic"},
|
||||
{"ETH", "Ethereum"},
|
||||
{"ETHARBITRUM", "Ethereum (Arbitrum)"},
|
||||
{"ETHBASE", "Ethereum (Base)"},
|
||||
{"ETHZKSYNC", "Ethereum (ZkSync)"},
|
||||
{"WETHARBITRUM", "Wrapped ETH (Arbitrum)"},
|
||||
{"WETHETH", "Wrapped ETH (ERC20)"},
|
||||
{"FTM", "Fantom"},
|
||||
{"KCS", "KuCoin Token"},
|
||||
{"LINK", "Chainlink (ERC20)"},
|
||||
{"LTC", "Litecoin"},
|
||||
{"MANAETH", "Decentraland (ERC20)"},
|
||||
{"MATIC", "Polygon"},
|
||||
{"MATICETH", "Polygon (ERC20)"},
|
||||
{"MKR", "Maker (ERC20)"},
|
||||
{"PAXGETH", "PAX Gold (ERC20)"},
|
||||
{"POL", "Polygon"},
|
||||
{"POLETH", "Polygon (ERC20)"},
|
||||
{"SHIB", "SHIBA INU (ERC20)"},
|
||||
{"SHIBBSC", "SHIBA INU (BEP20)"},
|
||||
{"SOL", "Solana"},
|
||||
{"WSOL", "Wrapped SOL (Solana)"},
|
||||
{"TON", "Toncoin"},
|
||||
{"TRX", "Tron"},
|
||||
{"TUSD", "TrueUSD (ERC20)"},
|
||||
{"TWT", "Trust Wallet Token (BEP2)"},
|
||||
{"TWTBSC", "Trust Wallet Token (BEP20)"},
|
||||
{"USDCARBITRUM", "USD Coin (Arbitrum)"},
|
||||
{"USDCBSC", "USD Coin (BEP20)"},
|
||||
{"USDCETH", "USD Coin (ERC20)"},
|
||||
{"USDCMATIC", "USD Coin (Polygon)"},
|
||||
{"USDCSOL", "USD Coin (Solana)"},
|
||||
{"USDCTRC", "USD Coin (TRC20)"},
|
||||
{"USDP", "Pax Dollar (ERC20)"},
|
||||
{"USDT", "Tether (ERC20)"},
|
||||
{"USDTBSC", "Tether (BEP20)"},
|
||||
{"USDTMATIC", "Tether (Polygon)"},
|
||||
{"USDTSOL", "Tether (Solana)"},
|
||||
{"USDTTRC", "Tether (TRC20)"},
|
||||
{"VET", "VeChain"},
|
||||
{"XLM", "Stellar Lumens"},
|
||||
{"XMR", "Monero"},
|
||||
{"XRP", "Ripple"},
|
||||
{"XTZ", "Tezos"},
|
||||
@@ -68,8 +82,8 @@ namespace BTCPayServer.Plugins.FixedFloat
|
||||
{"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.Data
|
||||
@using BTCPayServer.Plugins.FixedFloat
|
||||
@using BTCPayServer.Services.Invoices
|
||||
@using BTCPayServer.Services.Stores
|
||||
@using Microsoft.AspNetCore.Mvc.TagHelpers
|
||||
@model BTCPayServer.Plugins.FixedFloat.FixedFloatSettings
|
||||
@inject BTCPayNetworkProvider BTCPayNetworkProvider
|
||||
@inject PaymentMethodHandlerDictionary PaymentMethodHandlerDictionary
|
||||
@{
|
||||
ViewData.SetActivePage("FixedFloat", "FixedFloat", "FixedFloat");
|
||||
var store = Context.GetStoreData();
|
||||
var allowedPaymentMethods = store.GetEnabledPaymentIds(BTCPayNetworkProvider)
|
||||
.Select(pmi => new SelectListItem(pmi.ToPrettyString(), pmi.ToString()))
|
||||
var allowedPaymentMethods = store.GetEnabledPaymentIds()
|
||||
.Select(pmi => new SelectListItem(pmi.ToString(), pmi.ToString()))
|
||||
.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
|
||||
@inject FixedFloatService FixedFloatService
|
||||
@model BTCPayServer.Models.InvoicingModels.PaymentModel
|
||||
@model BTCPayServer.Models.InvoicingModels.CheckoutModel
|
||||
@{
|
||||
var storeId = Model.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)
|
||||
{
|
||||
@@ -41,7 +46,7 @@
|
||||
const result = this.$parent.paymentMethodId === "FixedFloat";
|
||||
|
||||
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;
|
||||
}
|
||||
this.$parent.paymentMethodId = this.preferredToCurrency;
|
||||
@@ -53,7 +58,7 @@
|
||||
return result;
|
||||
},
|
||||
lightning () {
|
||||
if (!this.model.onChainWithLnInvoiceFallback || this.model.paymentMethodId !== "BTC"){
|
||||
if (!this.model.onChainWithLnInvoiceFallback || this.model.paymentMethodId !== "BTC-CHAIN"){
|
||||
return null;
|
||||
}
|
||||
const index = this.model.invoiceBitcoinUrl.indexOf("lightning=");
|
||||
@@ -63,9 +68,9 @@
|
||||
return this.model.invoiceBitcoinUrl.slice(index + "lightning=".length);
|
||||
},
|
||||
url () {
|
||||
|
||||
const address= this.lightning || this.model.btcAddress;
|
||||
return "https://widget.fixedfloat.com/?" +
|
||||
debugger;
|
||||
const address= this.lightning || this.model.address;
|
||||
return "https://widget.ff.io/?" +
|
||||
`to=${this.settleMethodId}` +
|
||||
"&lockReceive=true&ref=fkbyt39c" +
|
||||
`&address=${address}` +
|
||||
@@ -76,9 +81,9 @@
|
||||
return this.model.paymentMethodId;
|
||||
},
|
||||
settleMethodId () {
|
||||
return this.currency.endsWith('LightningLike') || this.currency.endsWith('LNURLPay') || this.lightning
|
||||
return this.currency.endsWith('LN') || this.currency.endsWith('LNURL') || this.lightning
|
||||
? 'BTCLN'
|
||||
: this.currency.replace('_BTCLike', '').replace('_MoneroLike', '').replace('_ZcashLike', '').toUpperCase();
|
||||
: this.currency.replace('-CHAIN', '').replace('_CHAIN', '').toUpperCase();
|
||||
},
|
||||
explicitQuery (){
|
||||
const isExplicit = !!this.explicitId;
|
||||
@@ -91,7 +96,7 @@
|
||||
: `&lockType=true&hideType=true&lockAmount=true&toAmount=${this.amountDue}`;
|
||||
},
|
||||
amountDue () {
|
||||
return this.model.btcDue * (1 + (markupPercentage / 100));
|
||||
return this.model.due * (1 + (markupPercentage / 100));
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
@using BTCPayServer.Plugins.FixedFloat
|
||||
@model BTCPayServer.Models.InvoicingModels.PaymentModel
|
||||
@model BTCPayServer.Models.InvoicingModels.CheckoutModel
|
||||
@inject FixedFloatService FixedFloatService
|
||||
@{
|
||||
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>
|
||||
<Product>Liquid+</Product>
|
||||
<Description>Enhanced support for the liquid network.</Description>
|
||||
<Version>1.1.4</Version>
|
||||
<Version>1.1.5</Version>
|
||||
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
|
||||
</PropertyGroup>
|
||||
|
||||
|
||||
@@ -10,7 +10,10 @@ using BTCPayServer.Abstractions.Extensions;
|
||||
using BTCPayServer.Abstractions.Models;
|
||||
using BTCPayServer.Client;
|
||||
using BTCPayServer.Common;
|
||||
using BTCPayServer.Data;
|
||||
using BTCPayServer.Plugins.Altcoins;
|
||||
using BTCPayServer.Services.Invoices;
|
||||
using BTCPayServer.Services.Stores;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc.ViewFeatures;
|
||||
@@ -25,20 +28,24 @@ namespace BTCPayServer.Plugins.LiquidPlus.Controllers
|
||||
[AutoValidateAntiforgeryToken]
|
||||
public class StoreLiquidController : Controller
|
||||
{
|
||||
private readonly PaymentMethodHandlerDictionary _paymentMethodHandlerDictionary;
|
||||
private readonly StoreRepository _storeRepository;
|
||||
private readonly BTCPayNetworkProvider _btcPayNetworkProvider;
|
||||
private readonly BTCPayServerClient _client;
|
||||
private readonly IExplorerClientProvider _explorerClientProvider;
|
||||
|
||||
public StoreLiquidController(BTCPayNetworkProvider btcPayNetworkProvider,
|
||||
BTCPayServerClient client, IExplorerClientProvider explorerClientProvider)
|
||||
public StoreLiquidController(PaymentMethodHandlerDictionary paymentMethodHandlerDictionary,
|
||||
StoreRepository storeRepository, BTCPayNetworkProvider btcPayNetworkProvider,
|
||||
IExplorerClientProvider explorerClientProvider)
|
||||
{
|
||||
_paymentMethodHandlerDictionary = paymentMethodHandlerDictionary;
|
||||
_storeRepository = storeRepository;
|
||||
_btcPayNetworkProvider = btcPayNetworkProvider;
|
||||
_client = client;
|
||||
_explorerClientProvider = explorerClientProvider;
|
||||
}
|
||||
|
||||
[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>();
|
||||
var allNetworks = _btcPayNetworkProvider.GetAll().OfType<ElementsBTCPayNetwork>()
|
||||
@@ -49,12 +56,19 @@ namespace BTCPayServer.Plugins.LiquidPlus.Controllers
|
||||
.Distinct();
|
||||
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))
|
||||
.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()
|
||||
{
|
||||
@@ -64,7 +78,7 @@ namespace BTCPayServer.Plugins.LiquidPlus.Controllers
|
||||
return View(new GenerateLiquidImportScripts());
|
||||
}
|
||||
|
||||
foreach (var der in paymentMethods)
|
||||
foreach (var der in paymentMethodsGroupedByNetworkCode)
|
||||
{
|
||||
var network = _btcPayNetworkProvider.GetNetwork<ElementsBTCPayNetwork>(der.Key);
|
||||
var nbxnet = network.NBXplorerNetwork;
|
||||
@@ -79,12 +93,12 @@ namespace BTCPayServer.Plugins.LiquidPlus.Controllers
|
||||
generated.Add(der.Key, sb.ToString());
|
||||
continue;
|
||||
}
|
||||
var derivationSchemesForNetwork = der.GroupBy(data => data.DerivationScheme);
|
||||
|
||||
var derivationSchemesForNetwork = der.GroupBy(data => data.DerivationSchemeSettings);
|
||||
|
||||
foreach (var paymentMethodDerivationScheme in derivationSchemesForNetwork)
|
||||
{
|
||||
var derivatonScheme =
|
||||
nbxnet.DerivationStrategyFactory.Parse(paymentMethodDerivationScheme.Key);
|
||||
var derivatonScheme = paymentMethodDerivationScheme.Key.AccountDerivation;
|
||||
var sameWalletCryptoCodes = paymentMethodDerivationScheme.Select(data => data.CryptoCode).ToArray();
|
||||
var matchedExistingKey = privKeys.Where(pair => sameWalletCryptoCodes.Contains(pair.Key));
|
||||
BitcoinExtKey key = null;
|
||||
@@ -94,14 +108,12 @@ namespace BTCPayServer.Plugins.LiquidPlus.Controllers
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
key = await explorerClient.GetMetadataAsync<BitcoinExtKey>(derivatonScheme,
|
||||
WellknownMetadataKeys.AccountHDKey);
|
||||
}
|
||||
|
||||
if (key != null)
|
||||
{
|
||||
|
||||
foreach (var paymentMethodData in paymentMethodDerivationScheme)
|
||||
{
|
||||
privKeys.TryAdd(paymentMethodData.CryptoCode, key);
|
||||
@@ -139,14 +151,14 @@ namespace BTCPayServer.Plugins.LiquidPlus.Controllers
|
||||
{
|
||||
sb.AppendLine("elements-cli stop");
|
||||
sb.AppendLine("elementsd -rescan");
|
||||
|
||||
}
|
||||
|
||||
generated.Add(der.Key, sb.ToString());
|
||||
}
|
||||
|
||||
return View(new GenerateLiquidImportScripts()
|
||||
{
|
||||
Wallets = paymentMethods.SelectMany(settings =>
|
||||
Wallets = paymentMethodsGroupedByNetworkCode.SelectMany(settings =>
|
||||
settings.Select(data =>
|
||||
new GenerateLiquidImportScripts.GenerateLiquidImportScriptWalletKeyVm()
|
||||
{
|
||||
@@ -199,10 +211,9 @@ namespace BTCPayServer.Plugins.LiquidPlus.Controllers
|
||||
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)
|
||||
{
|
||||
vm.AddModelError(scripts => scripts.Wallets[index].ManualKey, "cannot handle multsig", this);
|
||||
@@ -250,7 +261,8 @@ namespace BTCPayServer.Plugins.LiquidPlus.Controllers
|
||||
|
||||
return await GenerateLiquidScript(storeId, privKeys);
|
||||
}
|
||||
public class GenerateLiquidImportScripts
|
||||
|
||||
public class GenerateLiquidImportScripts
|
||||
{
|
||||
public class GenerateLiquidImportScriptWalletKeyVm
|
||||
{
|
||||
@@ -266,6 +278,7 @@ public class GenerateLiquidImportScripts
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
namespace XX
|
||||
{
|
||||
public static class ModelStateExtensions
|
||||
@@ -275,7 +288,9 @@ namespace XX
|
||||
string message,
|
||||
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);
|
||||
controller.ModelState.AddModelError(key, message);
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ namespace BTCPayServer.Plugins.LiquidPlus
|
||||
{
|
||||
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)
|
||||
@@ -31,11 +31,11 @@ namespace BTCPayServer.Plugins.LiquidPlus
|
||||
if (services.BootstrapServices.GetRequiredService<NBXplorerNetworkProvider>()
|
||||
.GetFromCryptoCode("LBTC") is null || !services.BootstrapServices.GetRequiredService<SelectedChains>().Contains("LBTC"))
|
||||
return;
|
||||
services.AddSingleton<IUIExtension>(new UIExtension("LiquidNav", "store-integrations-nav"));
|
||||
services.AddSingleton<IUIExtension>(new UIExtension("OnChainWalletSetupLiquidExtension",
|
||||
"onchain-wallet-setup-post-body"));
|
||||
services.AddSingleton<IUIExtension>(new UIExtension("CustomLiquidAssetsNavExtension", "server-nav"));
|
||||
services.AddSingleton<IUIExtension>(new UIExtension("StoreNavLiquidExtension", "store-nav"));
|
||||
services.AddUIExtension("store-integrations-nav", "LiquidNav");
|
||||
services.AddUIExtension("onchain-wallet-setup-post-body", "OnChainWalletSetupLiquidExtension");
|
||||
services.AddUIExtension("server-nav", "CustomLiquidAssetsNavExtension");
|
||||
services.AddUIExtension("store-nav", "StoreNavLiquidExtension");
|
||||
|
||||
services.AddSingleton<CustomLiquidAssetsRepository>();
|
||||
|
||||
|
||||
@@ -53,12 +53,11 @@ namespace BTCPayServer.Plugins.LiquidPlus
|
||||
CryptoCode: "LBTC"
|
||||
})
|
||||
.ImplementationInstance;
|
||||
|
||||
var pmi = PaymentTypes.CHAIN.GetPaymentMethodId("LBTC");
|
||||
var tlProvider = (TransactionLinkProviders.Entry) services.Single(descriptor =>
|
||||
descriptor.ServiceType == typeof(TransactionLinkProviders.Entry) &&
|
||||
descriptor.ImplementationInstance is TransactionLinkProviders.Entry
|
||||
{
|
||||
PaymentMethodId: {CryptoCode: "LBTC"}
|
||||
})
|
||||
descriptor.ImplementationInstance is TransactionLinkProviders.Entry entry && entry.PaymentMethodId == pmi)
|
||||
.ImplementationInstance;
|
||||
settings.Items.ForEach(configuration =>
|
||||
|
||||
@@ -80,7 +79,6 @@ namespace BTCPayServer.Plugins.LiquidPlus
|
||||
NetworkCryptoCode = template.NetworkCryptoCode,
|
||||
DefaultSettings = template.DefaultSettings,
|
||||
ElectrumMapping = template.ElectrumMapping,
|
||||
BlockExplorerLink = template.BlockExplorerLink,
|
||||
ReadonlyWallet = template.ReadonlyWallet,
|
||||
SupportLightning = false,
|
||||
SupportPayJoin = false,
|
||||
@@ -92,7 +90,7 @@ namespace BTCPayServer.Plugins.LiquidPlus
|
||||
VaultSupported = template.VaultSupported,
|
||||
MaxTrackedConfirmation = template.MaxTrackedConfirmation,
|
||||
SupportRBF = template.SupportRBF
|
||||
}).AddTransactionLinkProvider(new PaymentMethodId(code, PaymentTypes.BTCLike), tlProvider.Provider);
|
||||
}).AddTransactionLinkProvider(code, tlProvider.Provider);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="Resources\**" />
|
||||
<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="Laraue.EfCoreTriggers.PostgreSql" Version="8.0.3" />
|
||||
<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 Laraue.EfCoreTriggers.PostgreSql.Extensions;
|
||||
using BTCPayServer.Data;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Npgsql.EntityFrameworkCore.PostgreSQL.Infrastructure;
|
||||
|
||||
namespace BTCPayServer.Plugins.MicroNode;
|
||||
|
||||
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>();
|
||||
ConfigureBuilder(builder);
|
||||
builder.UsePostgreSqlTriggers();
|
||||
|
||||
builder.UseLoggerFactory(_loggerFactory);
|
||||
builder.AddInterceptors(MigrationInterceptor.Instance);
|
||||
ConfigureBuilder(builder, npgsqlOptionsAction);
|
||||
return new MicroNodeContext(builder.Options);
|
||||
}
|
||||
}
|
||||
@@ -8,6 +8,7 @@ using BTCPayServer.Client;
|
||||
using BTCPayServer.Data;
|
||||
using BTCPayServer.Payments;
|
||||
using BTCPayServer.Payments.Lightning;
|
||||
using BTCPayServer.Services.Invoices;
|
||||
using BTCPayServer.Services.Stores;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
@@ -17,14 +18,17 @@ namespace BTCPayServer.Plugins.MicroNode;
|
||||
[Route("plugins/micronode")]
|
||||
public class MicroNodeController : Controller
|
||||
{
|
||||
private readonly PaymentMethodHandlerDictionary _paymentMethodHandlerDictionary;
|
||||
private readonly MicroNodeService _microNodeService;
|
||||
private readonly StoreRepository _storeRepository;
|
||||
private readonly BTCPayNetworkProvider _networkProvider;
|
||||
private readonly IAuthorizationService _authorizationService;
|
||||
|
||||
public MicroNodeController(MicroNodeService microNodeService, StoreRepository storeRepository,
|
||||
public MicroNodeController(
|
||||
PaymentMethodHandlerDictionary paymentMethodHandlerDictionary,MicroNodeService microNodeService, StoreRepository storeRepository,
|
||||
BTCPayNetworkProvider networkProvider, IAuthorizationService authorizationService)
|
||||
{
|
||||
_paymentMethodHandlerDictionary = paymentMethodHandlerDictionary;
|
||||
_microNodeService = microNodeService;
|
||||
_storeRepository = storeRepository;
|
||||
_networkProvider = networkProvider;
|
||||
@@ -66,11 +70,8 @@ public class MicroNodeController : Controller
|
||||
ModelState.AddModelError("masterStoreId", "Master cannot be the same as this store");
|
||||
return View(settings);
|
||||
}
|
||||
|
||||
var existing = store.GetSupportedPaymentMethods(_networkProvider).OfType<LightningSupportedPaymentMethod>()
|
||||
.FirstOrDefault(method =>
|
||||
method.PaymentId.PaymentType == LightningPaymentType.Instance &&
|
||||
method.PaymentId.CryptoCode == network.CryptoCode);
|
||||
var pmi = PaymentTypes.LN.GetPaymentMethodId(network.CryptoCode);
|
||||
var existing = store.GetPaymentMethodConfig<LightningPaymentMethodConfig>(pmi, _paymentMethodHandlerDictionary);
|
||||
var isSet = settings?.Key is not null;
|
||||
settings ??= new MicroNodeStoreSettings();
|
||||
settings.Key ??= Guid.NewGuid().ToString();
|
||||
@@ -118,12 +119,10 @@ public class MicroNodeController : Controller
|
||||
}
|
||||
|
||||
|
||||
existing ??= new LightningSupportedPaymentMethod()
|
||||
{
|
||||
CryptoCode = "BTC"
|
||||
};
|
||||
existing ??= new();
|
||||
existing.SetLightningUrl(mlc);
|
||||
store.SetSupportedPaymentMethod(existing);
|
||||
|
||||
store.SetPaymentMethodConfig(_paymentMethodHandlerDictionary[pmi], existing);
|
||||
|
||||
|
||||
await _microNodeService.Set(storeId, settings, masterStoreId);
|
||||
@@ -145,7 +144,7 @@ public class MicroNodeController : Controller
|
||||
|
||||
if (isStoreSetToThisMicro)
|
||||
{
|
||||
store.SetSupportedPaymentMethod(existing.PaymentId, null);
|
||||
store.SetPaymentMethodConfig(_paymentMethodHandlerDictionary[pmi], null);
|
||||
await _storeRepository.UpdateStore(store);
|
||||
}
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ public class MicroNodePlugin:BaseBTCPayServerPlugin
|
||||
{
|
||||
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.Payments;
|
||||
using BTCPayServer.Payments.Lightning;
|
||||
using BTCPayServer.Payouts;
|
||||
using BTCPayServer.Services;
|
||||
using BTCPayServer.Services.Invoices;
|
||||
using BTCPayServer.Services.Stores;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
@@ -34,6 +36,7 @@ public class MicroNodeService : EventHostedServiceBase
|
||||
private readonly ILogger<MicroNodeService> _logger;
|
||||
private readonly PullPaymentHostedService _pullPaymentHostedService;
|
||||
private readonly IOptions<LightningNetworkOptions> _lightningNetworkOptions;
|
||||
private readonly PaymentMethodHandlerDictionary _paymentMethodHandlerDictionary;
|
||||
private static readonly ConcurrentDictionary<string, long> ExpectedCounter = new();
|
||||
private readonly TaskCompletionSource _init = new();
|
||||
private Dictionary<string, MicroNodeSettings> _ownerSettings;
|
||||
@@ -53,6 +56,7 @@ public class MicroNodeService : EventHostedServiceBase
|
||||
EventAggregator eventAggregator,
|
||||
PullPaymentHostedService pullPaymentHostedService,
|
||||
IOptions<LightningNetworkOptions> lightningNetworkOptions,
|
||||
PaymentMethodHandlerDictionary paymentMethodHandlerDictionary,
|
||||
IServiceProvider serviceProvider) : base(eventAggregator, logger)
|
||||
{
|
||||
_network = btcPayNetworkProvider.BTC;
|
||||
@@ -63,6 +67,7 @@ public class MicroNodeService : EventHostedServiceBase
|
||||
_logger = logger;
|
||||
_pullPaymentHostedService = pullPaymentHostedService;
|
||||
_lightningNetworkOptions = lightningNetworkOptions;
|
||||
_paymentMethodHandlerDictionary = paymentMethodHandlerDictionary;
|
||||
_serviceProvider = serviceProvider;
|
||||
}
|
||||
|
||||
@@ -124,17 +129,20 @@ public class MicroNodeService : EventHostedServiceBase
|
||||
{
|
||||
var b = payout.GetBlob(_btcPayNetworkJsonSerializerSettings);
|
||||
|
||||
List<MicroTransaction> res = new();
|
||||
res.Add(new MicroTransaction()
|
||||
List<MicroTransaction> res =
|
||||
[
|
||||
new()
|
||||
{
|
||||
Id = payout.Id,
|
||||
AccountId = key,
|
||||
Amount = -LightMoney.Coins(b.CryptoAmount.Value).MilliSatoshi,
|
||||
Amount = -LightMoney.Coins(payout.Amount!.Value).MilliSatoshi,
|
||||
Accounted = payout.State != PayoutState.Cancelled,
|
||||
Active = payout.State is PayoutState.AwaitingApproval or PayoutState.AwaitingPayment
|
||||
or PayoutState.InProgress,
|
||||
Type = "Payout"
|
||||
});
|
||||
}
|
||||
|
||||
];
|
||||
|
||||
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();
|
||||
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)
|
||||
{
|
||||
return null;
|
||||
@@ -336,9 +344,9 @@ public class MicroNodeService : EventHostedServiceBase
|
||||
return null;
|
||||
}
|
||||
|
||||
var lightningConnectionString = store.GetSupportedPaymentMethods(_btcPayNetworkProvider)
|
||||
.OfType<LightningSupportedPaymentMethod>()
|
||||
.FirstOrDefault(method => method.CryptoCode == _network.CryptoCode)?.CreateLightningClient(_network,
|
||||
var pmi = PaymentTypes.LN.GetPaymentMethodId(_network.CryptoCode);
|
||||
var lightningConnectionString = store.GetPaymentMethodConfig<LightningPaymentMethodConfig>(pmi, _paymentMethodHandlerDictionary)
|
||||
?.CreateLightningClient(_network,
|
||||
_lightningNetworkOptions.Value, _serviceProvider.GetService<LightningClientFactoryService>());
|
||||
return lightningConnectionString;
|
||||
}
|
||||
@@ -616,7 +624,7 @@ public class MicroNodeService : EventHostedServiceBase
|
||||
StoreId = masterClients.Key,
|
||||
Destination = new LNURLPayClaimDestinaton(destination),
|
||||
PreApprove = true,
|
||||
PaymentMethodId = new PaymentMethodId("BTC", LightningPaymentType.Instance),
|
||||
PayoutMethodId = PayoutTypes.LN.GetPayoutMethodId("BTC"),
|
||||
Metadata = JObject.FromObject(new
|
||||
{
|
||||
Source = $"MicroNode on store {storeId.Key}"
|
||||
@@ -667,7 +675,7 @@ public class MicroNodeService : EventHostedServiceBase
|
||||
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)
|
||||
{
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
<PropertyGroup>
|
||||
<Product>Nostr</Product>
|
||||
<Description>NIP5 addresses, Zap support, Nostr Wallet Connect Lightning support</Description>
|
||||
<Version>1.1.13</Version>
|
||||
<Version>1.1.14</Version>
|
||||
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
|
||||
</PropertyGroup>
|
||||
<!-- Plugin development properties -->
|
||||
|
||||
@@ -13,7 +13,7 @@ namespace BTCPayServer.Plugins.NIP05
|
||||
{
|
||||
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)
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
<div class="col-xl-8 col-xxl-constrain">
|
||||
<div class="form-group">
|
||||
<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">
|
||||
<input asp-for="Name" class="form-control"/>
|
||||
<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.Tasks;
|
||||
using BTCPayServer.Events;
|
||||
using BTCPayServer.Models.InvoicingModels;
|
||||
using BTCPayServer.Payments;
|
||||
using BTCPayServer.Services;
|
||||
using BTCPayServer.Services.Invoices;
|
||||
using BTCPayServer.Services.Stores;
|
||||
using Microsoft.Extensions.Caching.Memory;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using Microsoft.Extensions.Logging;
|
||||
@@ -24,6 +22,7 @@ public class Zapper : IHostedService
|
||||
{
|
||||
record PendingZapEvent(string[] relays, NostrEvent nostrEvent);
|
||||
|
||||
private readonly PaymentMethodHandlerDictionary _paymentMethodHandlerDictionary;
|
||||
private readonly EventAggregator _eventAggregator;
|
||||
private readonly Nip5Controller _nip5Controller;
|
||||
private readonly IMemoryCache _memoryCache;
|
||||
@@ -51,7 +50,9 @@ public class Zapper : IHostedService
|
||||
}
|
||||
|
||||
|
||||
public Zapper(EventAggregator eventAggregator,
|
||||
public Zapper(
|
||||
PaymentMethodHandlerDictionary paymentMethodHandlerDictionary,
|
||||
EventAggregator eventAggregator,
|
||||
Nip5Controller nip5Controller,
|
||||
IMemoryCache memoryCache,
|
||||
ILogger<Zapper> logger,
|
||||
@@ -59,6 +60,7 @@ public class Zapper : IHostedService
|
||||
InvoiceRepository invoiceRepository,
|
||||
NostrClientPool nostrClientPool)
|
||||
{
|
||||
_paymentMethodHandlerDictionary = paymentMethodHandlerDictionary;
|
||||
_eventAggregator = eventAggregator;
|
||||
_nip5Controller = nip5Controller;
|
||||
_memoryCache = memoryCache;
|
||||
@@ -150,7 +152,8 @@ public class Zapper : IHostedService
|
||||
{
|
||||
if (arg.EventCode != InvoiceEventCode.Completed && arg.EventCode != InvoiceEventCode.MarkedCompleted)
|
||||
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)
|
||||
{
|
||||
return;
|
||||
@@ -160,7 +163,6 @@ public class Zapper : IHostedService
|
||||
return;
|
||||
}
|
||||
|
||||
var pmd = (LNURLPayPaymentMethodDetails) pm.GetPaymentMethodDetails();
|
||||
var settings = await GetSettings();
|
||||
|
||||
var zapRequestEvent = JsonSerializer.Deserialize<NostrEvent>(zapRequest);
|
||||
@@ -174,7 +176,7 @@ public class Zapper : IHostedService
|
||||
new NostrEventTag
|
||||
{
|
||||
TagIdentifier = "bolt11",
|
||||
Data = new() {pmd.BOLT11}
|
||||
Data = new() {pm.Destination}
|
||||
},
|
||||
|
||||
new NostrEventTag()
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
<PropertyGroup>
|
||||
<Product>Prism</Product>
|
||||
<Description>Automated value splits for Bitcoin.</Description>
|
||||
<Version>1.2.8</Version>
|
||||
<Version>1.2.9</Version>
|
||||
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
|
||||
</PropertyGroup>
|
||||
<!-- Plugin development properties -->
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
@using BTCPayServer.HostedServices
|
||||
@using BTCPayServer.Payments
|
||||
@using BTCPayServer.PayoutProcessors
|
||||
@using BTCPayServer.Payouts
|
||||
@using Microsoft.AspNetCore.Http
|
||||
@using Microsoft.AspNetCore.Routing
|
||||
@using Microsoft.Extensions.Logging
|
||||
@@ -28,7 +29,7 @@ else
|
||||
{
|
||||
<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="*@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>
|
||||
|
||||
@foreach (var user in Users)
|
||||
@@ -201,8 +202,8 @@ else
|
||||
|
||||
public bool Loading { get; set; } = true;
|
||||
public List<LightningAddressData> Users { get; set; } = new();
|
||||
public PaymentMethodId pmi { get; set; } = new("BTC", LightningPaymentType.Instance);
|
||||
public PaymentMethodId pmichain { get; set; } = new("BTC", PaymentTypes.BTCLike);
|
||||
public PayoutMethodId pmi { get; set; } = PayoutTypes.LN.GetPayoutMethodId("BTC");
|
||||
public PayoutMethodId pmichain { get; set; } = PayoutTypes.CHAIN.GetPayoutMethodId("BTC");
|
||||
public bool NoPayoutProcessors { get; set; }
|
||||
|
||||
private string PrismEditButtonsFilter { get; set; }
|
||||
@@ -224,7 +225,7 @@ else
|
||||
var fetchProcessors = PayoutProcessorService.GetProcessors(new PayoutProcessorService.PayoutProcessorQuery()
|
||||
{
|
||||
Stores = new[] {StoreId},
|
||||
PaymentMethods = new[] {pmi.ToString(), pmichain.ToString()}
|
||||
PayoutMethods = new[] {pmi, pmichain}
|
||||
});
|
||||
|
||||
var tasks = new Task[]
|
||||
@@ -243,8 +244,8 @@ else
|
||||
EditContext.OnFieldChanged += FieldChanged;
|
||||
SatBreaker.PrismUpdated += SatBreakerOnPrismUpdated;
|
||||
//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 =>
|
||||
!new[] {pmi, pmichain}.Contains(data.GetPaymentMethodId()));
|
||||
NoPayoutProcessors = PayoutProcessorFactories.Any(factory => factory.GetSupportedPayoutMethods().Contains(pmi)) && (await fetchProcessors).All(data =>
|
||||
!new[] {pmi, pmichain}.Contains(data.GetPayoutMethodId()));
|
||||
|
||||
Loading = false;
|
||||
await InvokeAsync(StateHasChanged);
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
using System.Threading.Tasks;
|
||||
using BTCPayServer.Abstractions.Contracts;
|
||||
using BTCPayServer.Payments;
|
||||
using BTCPayServer.Payouts;
|
||||
|
||||
namespace BTCPayServer.Plugins.Prism;
|
||||
|
||||
@@ -19,7 +20,7 @@ public class LNURLPrismDestinationValidator : IPluginHookFilter
|
||||
return Task.FromResult<object>(new PrismDestinationValidationResult()
|
||||
{
|
||||
Success = true,
|
||||
PaymentMethod = new PaymentMethodId("BTC", PaymentTypes.LNURLPay)
|
||||
PayoutMethodId = PayoutTypes.LN.GetPayoutMethodId("BTC")
|
||||
});
|
||||
}
|
||||
catch (Exception e)
|
||||
@@ -30,7 +31,7 @@ public class LNURLPrismDestinationValidator : IPluginHookFilter
|
||||
return Task.FromResult<object>(new PrismDestinationValidationResult()
|
||||
{
|
||||
Success = true,
|
||||
PaymentMethod = new PaymentMethodId("BTC", PaymentTypes.LNURLPay)
|
||||
PayoutMethodId =PayoutTypes.LN.GetPayoutMethodId("BTC")
|
||||
});
|
||||
}
|
||||
catch (Exception)
|
||||
@@ -45,5 +46,5 @@ public class LNURLPrismDestinationValidator : IPluginHookFilter
|
||||
public class PrismDestinationValidationResult
|
||||
{
|
||||
public bool Success { get; set; }
|
||||
public PaymentMethodId PaymentMethod { get; set; }
|
||||
public PayoutMethodId PayoutMethodId { get; set; }
|
||||
}
|
||||
@@ -1,10 +1,9 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Threading.Tasks;
|
||||
using BTCPayServer.Abstractions.Contracts;
|
||||
using BTCPayServer.Data;
|
||||
using BTCPayServer.HostedServices;
|
||||
using BTCPayServer.Payments;
|
||||
using BTCPayServer.Payouts;
|
||||
using NBitcoin;
|
||||
using NBXplorer.DerivationStrategy;
|
||||
|
||||
@@ -35,7 +34,7 @@ public class OnChainPrismClaimCreate : IPluginHookFilter
|
||||
{
|
||||
claimRequest.Destination =
|
||||
new AddressClaimDestination(BitcoinAddress.Create(destStr, network.NBitcoinNetwork));
|
||||
claimRequest.PaymentMethodId = new PaymentMethodId("BTC", BitcoinPaymentType.Instance);
|
||||
claimRequest.PayoutMethodId = PayoutTypes.CHAIN.GetPayoutMethodId("BTC");
|
||||
return args;
|
||||
}
|
||||
catch (Exception)
|
||||
@@ -48,7 +47,7 @@ public class OnChainPrismClaimCreate : IPluginHookFilter
|
||||
|
||||
claimRequest.Destination =
|
||||
new AddressClaimDestination(add.Address);
|
||||
claimRequest.PaymentMethodId = new PaymentMethodId("BTC", BitcoinPaymentType.Instance);
|
||||
claimRequest.PayoutMethodId = PayoutTypes.CHAIN.GetPayoutMethodId("BTC");
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
|
||||
@@ -3,6 +3,7 @@ using System.Threading.Tasks;
|
||||
using BTCPayServer.Abstractions.Contracts;
|
||||
using BTCPayServer.Data;
|
||||
using BTCPayServer.Payments;
|
||||
using BTCPayServer.Payouts;
|
||||
using NBitcoin;
|
||||
using NBXplorer;
|
||||
|
||||
@@ -34,7 +35,7 @@ public class OnChainPrismDestinationValidator : IPluginHookFilter
|
||||
return Task.FromResult<object>(new PrismDestinationValidationResult()
|
||||
{
|
||||
Success = true,
|
||||
PaymentMethod = new PaymentMethodId("BTC", PaymentTypes.BTCLike)
|
||||
PayoutMethodId = PayoutTypes.CHAIN.GetPayoutMethodId("BTC")
|
||||
});
|
||||
}
|
||||
catch (Exception e)
|
||||
@@ -46,7 +47,7 @@ public class OnChainPrismDestinationValidator : IPluginHookFilter
|
||||
return Task.FromResult<object>(new PrismDestinationValidationResult()
|
||||
{
|
||||
Success = true,
|
||||
PaymentMethod = new PaymentMethodId("BTC", PaymentTypes.BTCLike)
|
||||
PayoutMethodId =PayoutTypes.CHAIN.GetPayoutMethodId("BTC")
|
||||
});
|
||||
}
|
||||
catch (Exception)
|
||||
|
||||
@@ -5,6 +5,7 @@ using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using BTCPayServer.Abstractions.Contracts;
|
||||
using BTCPayServer.Payments;
|
||||
using BTCPayServer.Payouts;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
@@ -30,7 +31,7 @@ public class OpenSatsDestinationValidator : IPluginHookFilter
|
||||
|
||||
var parts = args1.ToLowerInvariant().Split(":", StringSplitOptions.RemoveEmptyEntries);
|
||||
var project = "general_fund";
|
||||
var paymentMethod = new PaymentMethodId("BTC", PaymentTypes.LightningLike);
|
||||
var paymentMethod = PayoutTypes.LN.GetPayoutMethodId("BTC");
|
||||
if (parts.Length > 1)
|
||||
{
|
||||
project = parts[1];
|
||||
@@ -38,12 +39,11 @@ public class OpenSatsDestinationValidator : IPluginHookFilter
|
||||
|
||||
if (parts.Length > 2)
|
||||
{
|
||||
paymentMethod = PaymentMethodId.Parse(parts[2]);
|
||||
paymentMethod = PayoutMethodId.Parse(parts[2]);
|
||||
}
|
||||
|
||||
|
||||
var handler = _serviceProvider.GetServices<IPayoutHandler>().FindPayoutHandler(paymentMethod);
|
||||
if (handler is null)
|
||||
if (_serviceProvider.GetService<PayoutMethodHandlerDictionary>().TryGetValue(paymentMethod, out var handler))
|
||||
{
|
||||
result.Success = false;
|
||||
}
|
||||
@@ -63,7 +63,7 @@ public class OpenSatsDestinationValidator : IPluginHookFilter
|
||||
var invoiceBtcpayModel = JObject.Parse(await httpClient.GetStringAsync(invoiceUrl).ConfigureAwait(false));
|
||||
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)
|
||||
{
|
||||
|
||||
@@ -72,7 +72,7 @@ public class OpenSatsDestinationValidator : IPluginHookFilter
|
||||
|
||||
|
||||
result.Success = true;
|
||||
result.PaymentMethod = paymentMethod;
|
||||
result.PayoutMethodId = paymentMethod;
|
||||
return result;
|
||||
}
|
||||
catch (Exception e)
|
||||
|
||||
@@ -1,18 +1,12 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using BTCPayServer.Abstractions.Contracts;
|
||||
using BTCPayServer.Abstractions.Custodians;
|
||||
using BTCPayServer.Abstractions.Extensions;
|
||||
using BTCPayServer.Data;
|
||||
using BTCPayServer.HostedServices;
|
||||
using BTCPayServer.Payments;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using BTCPayServer.Payouts;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using NBitcoin;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
namespace BTCPayServer.Plugins.Prism;
|
||||
@@ -41,7 +35,7 @@ public class OpenSatsPrismClaimCreate : IPluginHookFilter
|
||||
|
||||
var parts = args1.Split(":", StringSplitOptions.RemoveEmptyEntries);
|
||||
var project = "opensats";
|
||||
var paymentMethod = new PaymentMethodId("BTC", PaymentTypes.LightningLike);
|
||||
var paymentMethod = PayoutTypes.LN.GetPayoutMethodId("BTC");
|
||||
if (parts.Length > 1)
|
||||
{
|
||||
project = parts[1];
|
||||
@@ -49,11 +43,11 @@ public class OpenSatsPrismClaimCreate : IPluginHookFilter
|
||||
|
||||
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)
|
||||
{
|
||||
return null;
|
||||
@@ -75,7 +69,7 @@ public class OpenSatsPrismClaimCreate : IPluginHookFilter
|
||||
var destination = invoiceBtcpayModel.Value<string>("btcAddress");
|
||||
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)
|
||||
{
|
||||
|
||||
@@ -88,7 +82,7 @@ public class OpenSatsPrismClaimCreate : IPluginHookFilter
|
||||
});
|
||||
|
||||
claimRequest.Destination = claimDestination.destination;
|
||||
claimRequest.PaymentMethodId = paymentMethod;
|
||||
claimRequest.PayoutMethodId = paymentMethod;
|
||||
|
||||
return claimRequest;
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ public class PrismPlugin : BaseBTCPayServerPlugin
|
||||
{
|
||||
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)
|
||||
|
||||
@@ -20,5 +20,5 @@ public class PrismDestination
|
||||
public string Destination { get; set; }
|
||||
public decimal? Reserve { 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.Payments;
|
||||
using BTCPayServer.Payments.Lightning;
|
||||
using BTCPayServer.Payouts;
|
||||
using BTCPayServer.Services;
|
||||
using BTCPayServer.Services.Invoices;
|
||||
using BTCPayServer.Services.Stores;
|
||||
@@ -47,13 +48,13 @@ namespace BTCPayServer.Plugins.Prism
|
||||
{
|
||||
private readonly StoreRepository _storeRepository;
|
||||
private readonly ILogger<SatBreaker> _logger;
|
||||
private readonly LightningAddressService _lightningAddressService;
|
||||
private readonly PullPaymentHostedService _pullPaymentHostedService;
|
||||
private readonly LightningLikePayoutHandler _lightningLikePayoutHandler;
|
||||
private readonly BTCPayNetworkProvider _btcPayNetworkProvider;
|
||||
private readonly LightningClientFactoryService _lightningClientFactoryService;
|
||||
private readonly IOptions<LightningNetworkOptions> _lightningNetworkOptions;
|
||||
private readonly BTCPayNetworkJsonSerializerSettings _btcPayNetworkJsonSerializerSettings;
|
||||
private readonly PaymentMethodHandlerDictionary _paymentMethodHandlerDictionary;
|
||||
private readonly PayoutMethodHandlerDictionary _payoutMethodHandlerDictionary;
|
||||
private readonly IPluginHookService _pluginHookService;
|
||||
private Dictionary<string, PrismSettings> _prismSettings;
|
||||
|
||||
@@ -62,24 +63,24 @@ namespace BTCPayServer.Plugins.Prism
|
||||
public SatBreaker(StoreRepository storeRepository,
|
||||
EventAggregator eventAggregator,
|
||||
ILogger<SatBreaker> logger,
|
||||
LightningAddressService lightningAddressService,
|
||||
PullPaymentHostedService pullPaymentHostedService,
|
||||
LightningLikePayoutHandler lightningLikePayoutHandler,
|
||||
BTCPayNetworkProvider btcPayNetworkProvider,
|
||||
LightningClientFactoryService lightningClientFactoryService,
|
||||
IOptions<LightningNetworkOptions> lightningNetworkOptions,
|
||||
BTCPayNetworkJsonSerializerSettings btcPayNetworkJsonSerializerSettings,
|
||||
PaymentMethodHandlerDictionary paymentMethodHandlerDictionary,
|
||||
PayoutMethodHandlerDictionary payoutMethodHandlerDictionary,
|
||||
IPluginHookService pluginHookService) : base(eventAggregator, logger)
|
||||
{
|
||||
_storeRepository = storeRepository;
|
||||
_logger = logger;
|
||||
_lightningAddressService = lightningAddressService;
|
||||
_pullPaymentHostedService = pullPaymentHostedService;
|
||||
_lightningLikePayoutHandler = lightningLikePayoutHandler;
|
||||
_btcPayNetworkProvider = btcPayNetworkProvider;
|
||||
_lightningClientFactoryService = lightningClientFactoryService;
|
||||
_lightningNetworkOptions = lightningNetworkOptions;
|
||||
_btcPayNetworkJsonSerializerSettings = btcPayNetworkJsonSerializerSettings;
|
||||
_paymentMethodHandlerDictionary = paymentMethodHandlerDictionary;
|
||||
_payoutMethodHandlerDictionary = payoutMethodHandlerDictionary;
|
||||
_pluginHookService = pluginHookService;
|
||||
}
|
||||
|
||||
@@ -148,17 +149,25 @@ namespace BTCPayServer.Plugins.Prism
|
||||
|
||||
foreach (var payout in storePayouts)
|
||||
{
|
||||
|
||||
if (!pendingPayouts.TryGetValue(payout.Id, out var pendingPayout))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if(payout.GetPayoutMethodId() is not { } payoutMethodId)
|
||||
continue;
|
||||
|
||||
if (!_payoutMethodHandlerDictionary.TryGetValue(payoutMethodId, out var handler))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
long toCredit = 0;
|
||||
switch (payout.State)
|
||||
{
|
||||
case PayoutState.Completed:
|
||||
|
||||
var proof = _lightningLikePayoutHandler.ParseProof(payout) as PayoutLightningBlob;
|
||||
var proof = handler.ParseProof(payout) as PayoutLightningBlob;
|
||||
|
||||
long? feePaid = null;
|
||||
if (!string.IsNullOrEmpty(proof?.PaymentHash))
|
||||
@@ -168,10 +177,10 @@ namespace BTCPayServer.Plugins.Prism
|
||||
var store = await _storeRepository.FindStore(payout.StoreDataId);
|
||||
|
||||
var network = _btcPayNetworkProvider.GetNetwork<BTCPayNetwork>("BTC");
|
||||
var id = new PaymentMethodId("BTC", LightningPaymentType.Instance);
|
||||
var existing = store.GetSupportedPaymentMethods(_btcPayNetworkProvider)
|
||||
.OfType<LightningSupportedPaymentMethod>()
|
||||
.FirstOrDefault(d => d.PaymentId == id);
|
||||
var id = PaymentTypes.LN.GetPaymentMethodId("BTC");
|
||||
var existing =
|
||||
store.GetPaymentMethodConfig<LightningPaymentMethodConfig>(id,
|
||||
_paymentMethodHandlerDictionary);
|
||||
if (existing?.GetExternalLightningUrl() is { } connectionString)
|
||||
{
|
||||
lnClient = _lightningClientFactoryService.Create(connectionString,
|
||||
@@ -313,12 +322,16 @@ namespace BTCPayServer.Plugins.Prism
|
||||
private (Split, LightMoney)[] DetermineMatches(PrismSettings prismSettings, InvoiceEntity entity)
|
||||
{
|
||||
//first check the primary thing - ln address
|
||||
var explicitPMI = new PaymentMethodId("BTC", LNURLPayPaymentType.Instance);
|
||||
var pm = entity.GetPaymentMethod(explicitPMI);
|
||||
var pmd = pm?.GetPaymentMethodDetails() as LNURLPayPaymentMethodDetails;
|
||||
List<(Split, LightMoney)> result = new();
|
||||
var explicitPMI = PaymentTypes.LNURL.GetPaymentMethodId("BTC");
|
||||
var pm = entity.GetPaymentPrompt(explicitPMI);
|
||||
|
||||
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)
|
||||
{
|
||||
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 =>
|
||||
{
|
||||
@@ -346,20 +360,25 @@ namespace BTCPayServer.Plugins.Prism
|
||||
switch (split.Source)
|
||||
{
|
||||
case "*":
|
||||
pmi = new PaymentMethodId("BTC", PaymentTypes.LightningLike);
|
||||
pmi = PaymentTypes.LN.GetPaymentMethodId("BTC");
|
||||
break;
|
||||
case "*All":
|
||||
break;
|
||||
case var s when PaymentTypes.TryParse(s.Substring(1), out var pType):
|
||||
|
||||
pmi = new PaymentMethodId("BTC", pType);
|
||||
case var s when s.StartsWith("*") && s.Substring(1) ==PaymentTypes.CHAIN.ToString():
|
||||
pmi = PaymentTypes.CHAIN.GetPaymentMethodId("BTC");
|
||||
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;
|
||||
case var s when !PaymentMethodId.TryParse(s.Substring(1), out pmi):
|
||||
valid = false;
|
||||
break;
|
||||
}
|
||||
|
||||
if (pmi is not null && pmi.CryptoCode != "BTC")
|
||||
if (pmi is not null && !pmi.ToString().StartsWith("BTC-"))
|
||||
{
|
||||
valid = false;
|
||||
}
|
||||
@@ -367,6 +386,7 @@ namespace BTCPayServer.Plugins.Prism
|
||||
return (pmi, valid, split);
|
||||
}).Where(tuple => tuple.valid).ToDictionary(split => split.pmi, split => split.split);
|
||||
|
||||
|
||||
while(payments.Any() || catchAlls.Any())
|
||||
{
|
||||
decimal paymentSum;
|
||||
@@ -511,9 +531,9 @@ namespace BTCPayServer.Plugins.Prism
|
||||
continue;
|
||||
}
|
||||
|
||||
var pmi = string.IsNullOrEmpty(destinationSettings?.PaymentMethodId) ||
|
||||
!PaymentMethodId.TryParse(destinationSettings?.PaymentMethodId, out var pmi2)
|
||||
? new PaymentMethodId("BTC", LightningPaymentType.Instance)
|
||||
var pmi = string.IsNullOrEmpty(destinationSettings?.PayoutMethodId) ||
|
||||
!PayoutMethodId.TryParse(destinationSettings?.PayoutMethodId, out var pmi2)
|
||||
? PayoutTypes.LN.GetPayoutMethodId("BTC")
|
||||
: pmi2;
|
||||
|
||||
var source = "Prism";
|
||||
@@ -526,7 +546,7 @@ namespace BTCPayServer.Plugins.Prism
|
||||
Destination = new PrismPlaceholderClaimDestination(destinationSettings?.Destination ?? destination),
|
||||
PreApprove = true,
|
||||
StoreId = storeId,
|
||||
PaymentMethodId = pmi,
|
||||
PayoutMethodId = pmi,
|
||||
Value = Money.Satoshis(payoutAmount).ToDecimal(MoneyUnit.BTC),
|
||||
Metadata = JObject.FromObject(new
|
||||
{
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
<PropertyGroup>
|
||||
<Product>SideShift</Product>
|
||||
<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>
|
||||
</PropertyGroup>
|
||||
<!-- 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.HostedServices;
|
||||
using BTCPayServer.Payments;
|
||||
using BTCPayServer.Payouts;
|
||||
using BTCPayServer.Services;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
@@ -26,7 +27,7 @@ namespace BTCPayServer.Plugins.SideShift
|
||||
{
|
||||
private readonly SideShiftService _sideShiftService;
|
||||
private readonly IHttpClientFactory _httpClientFactory;
|
||||
private readonly IEnumerable<IPayoutHandler> _payoutHandlers;
|
||||
private readonly PayoutMethodHandlerDictionary _payoutMethodHandlerDictionary;
|
||||
private readonly PullPaymentHostedService _pullPaymentHostedService;
|
||||
private readonly BTCPayNetworkJsonSerializerSettings _serializerSettings;
|
||||
private readonly ApplicationDbContextFactory _dbContextFactory;
|
||||
@@ -34,13 +35,13 @@ namespace BTCPayServer.Plugins.SideShift
|
||||
public SideShiftController(
|
||||
SideShiftService sideShiftService,
|
||||
IHttpClientFactory httpClientFactory,
|
||||
IEnumerable<IPayoutHandler> payoutHandlers,
|
||||
PayoutMethodHandlerDictionary payoutMethodHandlerDictionary,
|
||||
PullPaymentHostedService pullPaymentHostedService,
|
||||
BTCPayNetworkJsonSerializerSettings serializerSettings, ApplicationDbContextFactory dbContextFactory)
|
||||
{
|
||||
_sideShiftService = sideShiftService;
|
||||
_httpClientFactory = httpClientFactory;
|
||||
_payoutHandlers = payoutHandlers;
|
||||
_payoutMethodHandlerDictionary = payoutMethodHandlerDictionary;
|
||||
_pullPaymentHostedService = pullPaymentHostedService;
|
||||
_serializerSettings = serializerSettings;
|
||||
_dbContextFactory = dbContextFactory;
|
||||
@@ -111,19 +112,23 @@ namespace BTCPayServer.Plugins.SideShift
|
||||
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
|
||||
{
|
||||
handler = _payoutHandlers.FindPayoutHandler(pmi);
|
||||
if (handler == null)
|
||||
if (!_payoutMethodHandlerDictionary.TryGetValue(pmi, out handler))
|
||||
{
|
||||
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)
|
||||
{
|
||||
return this.CreateValidationError(ModelState);
|
||||
@@ -166,13 +171,13 @@ namespace BTCPayServer.Plugins.SideShift
|
||||
// shiftResponse.EnsureSuccessStatusCode();
|
||||
// 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
|
||||
{
|
||||
settleAddress = request.Destination,
|
||||
affiliateId = "qg0OrfHJV",
|
||||
settleMemo = request.Memo,
|
||||
depositCoin = pmi.CryptoCode,
|
||||
depositNetwork = pmi.PaymentType == LightningPaymentType.Instance ? "lightning" : null,
|
||||
depositCoin = cryptoCode,
|
||||
settleCoin = request.ShiftCurrency,
|
||||
settleNetwork = request.ShiftNetwork,
|
||||
}
|
||||
@@ -188,20 +193,20 @@ namespace BTCPayServer.Plugins.SideShift
|
||||
|
||||
|
||||
var destination =
|
||||
await handler.ParseAndValidateClaimDestination(pmi, shift.depositAddress, ppBlob,
|
||||
await handler.ParseAndValidateClaimDestination(shift.depositAddress, ppBlob,
|
||||
CancellationToken.None);
|
||||
|
||||
var claim = await _pullPaymentHostedService.Claim(new ClaimRequest()
|
||||
{
|
||||
PullPaymentId = pullPaymentId,
|
||||
Destination = destination.destination,
|
||||
PaymentMethodId = pmi,
|
||||
PayoutMethodId = pmi,
|
||||
Value = request.Amount
|
||||
});
|
||||
if (claim.Result == ClaimRequest.ClaimResult.Ok)
|
||||
{
|
||||
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);
|
||||
ctx.Attach(pp).State = EntityState.Modified;
|
||||
await ctx.SaveChangesAsync();
|
||||
@@ -242,19 +247,21 @@ namespace BTCPayServer.Plugins.SideShift
|
||||
private Client.Models.PayoutData ToModel(Data.PayoutData p)
|
||||
{
|
||||
var blob = p.GetBlob(_serializerSettings);
|
||||
var model = new Client.Models.PayoutData
|
||||
var model = new Client.Models.PayoutData()
|
||||
{
|
||||
Id = p.Id,
|
||||
PullPaymentId = p.PullPaymentDataId,
|
||||
Date = p.Date,
|
||||
Amount = blob.Amount,
|
||||
PaymentMethodAmount = blob.CryptoAmount,
|
||||
OriginalCurrency = p.OriginalCurrency,
|
||||
OriginalAmount = p.OriginalAmount,
|
||||
PayoutCurrency = p.Currency,
|
||||
PayoutAmount = p.Amount,
|
||||
Revision = blob.Revision,
|
||||
State = p.State,
|
||||
PayoutMethodId = p.PayoutMethodId,
|
||||
PaymentProof = p.GetProofBlobJson(),
|
||||
Destination = blob.Destination,
|
||||
PaymentMethod = p.PaymentMethodId,
|
||||
CryptoCode = p.GetPaymentMethodId().CryptoCode,
|
||||
PaymentProof = p.GetProofBlobJson()
|
||||
Metadata = blob.Metadata?? new JObject(),
|
||||
};
|
||||
return model;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
using BTCPayServer.Abstractions.Contracts;
|
||||
using BTCPayServer.Abstractions.Models;
|
||||
using BTCPayServer.Abstractions.Services;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
namespace BTCPayServer.Plugins.SideShift
|
||||
@@ -8,41 +7,22 @@ namespace BTCPayServer.Plugins.SideShift
|
||||
public class SideShiftPlugin : BaseBTCPayServerPlugin
|
||||
{
|
||||
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)
|
||||
{
|
||||
applicationBuilder.AddSingleton<SideShiftService>();
|
||||
applicationBuilder.AddHostedService(provider => provider.GetService<SideShiftService>());
|
||||
applicationBuilder.AddSingleton<IUIExtension>(new UIExtension("SideShift/SideShiftNav",
|
||||
"store-integrations-nav"));
|
||||
applicationBuilder.AddSingleton<IUIExtension>(new UIExtension("SideShift/PullPaymentViewInsert",
|
||||
"pullpayment-foot"));
|
||||
applicationBuilder.AddSingleton<IUIExtension>(new UIExtension("SideShift/StoreIntegrationSideShiftOption",
|
||||
"store-integrations-list"));
|
||||
|
||||
applicationBuilder.AddUIExtension("store-integrations-nav","SideShift/SideShiftNav");
|
||||
applicationBuilder.AddUIExtension("pullpayment-foot","SideShift/PullPaymentViewInsert");
|
||||
applicationBuilder.AddUIExtension("store-integrations-list", "SideShift/StoreIntegrationSideShiftOption");
|
||||
// Checkout v2
|
||||
applicationBuilder.AddSingleton<IUIExtension>(new UIExtension("SideShift/CheckoutPaymentMethodExtension",
|
||||
"checkout-payment-method"));
|
||||
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>();
|
||||
applicationBuilder.AddUIExtension("checkout-payment-method", "SideShift/CheckoutPaymentMethodExtension");
|
||||
applicationBuilder.AddUIExtension("checkout-payment","SideShift/CheckoutPaymentExtension");
|
||||
|
||||
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
|
||||
@inject BTCPayServer.Security.ContentSecurityPolicies csp
|
||||
@inject SideShiftService SideShiftService
|
||||
@model BTCPayServer.Models.InvoicingModels.PaymentModel
|
||||
@model BTCPayServer.Models.InvoicingModels.CheckoutModel
|
||||
@{
|
||||
var settings = await SideShiftService.GetSideShiftForInvoice(Model.InvoiceId, Model.StoreId);
|
||||
var preferredTargetPaymentMethodId = "";
|
||||
PaymentMethodId preferredTargetPaymentMethodId = null;
|
||||
if(!PaymentMethodId.TryParse(settings?.PreferredTargetPaymentMethodId, out var preferredPMI))
|
||||
{
|
||||
preferredTargetPaymentMethodId = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
preferredTargetPaymentMethodId = Model.AvailableCryptos.FirstOrDefault(crypto =>
|
||||
crypto.PaymentMethodId == settings.PreferredTargetPaymentMethodId ||
|
||||
(crypto.CryptoCode == preferredPMI.CryptoCode && crypto.PaymentMethodId.EndsWith(LNURLPayPaymentType.Instance.GetId()) || crypto.PaymentMethodId.EndsWith(LightningPaymentType.Instance.GetId())))?.PaymentMethodId;
|
||||
preferredTargetPaymentMethodId = Model.AvailablePaymentMethods.FirstOrDefault(crypto =>
|
||||
crypto.PaymentMethodId == preferredPMI )?.PaymentMethodId;
|
||||
}
|
||||
}
|
||||
@if (settings?.Enabled is true)
|
||||
@@ -25,7 +24,8 @@
|
||||
<template id="side-shift-checkout-template">
|
||||
<div class="payment-box">
|
||||
<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>
|
||||
</template>
|
||||
<script>
|
||||
@@ -48,7 +48,7 @@
|
||||
},200)
|
||||
|
||||
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;
|
||||
}
|
||||
this.$parent.paymentMethodId = this.preferredToCurrency;
|
||||
@@ -58,16 +58,7 @@
|
||||
|
||||
},
|
||||
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 () {
|
||||
return this.$i18n.i18next.t("conversion_body", this.model).replace(/\n/ig, '<br>');
|
||||
},
|
||||
@@ -76,16 +67,16 @@
|
||||
},
|
||||
settleMethodId () {
|
||||
|
||||
const toCurrency = this.currency.toLowerCase();
|
||||
const toCurrency = this.currency.toUpperCase();
|
||||
|
||||
if (toCurrency === "lbtc") {
|
||||
return 'liquid';
|
||||
} else if (toCurrency === "usdt") {
|
||||
return "usdtla";
|
||||
} else if (toCurrency.endsWith('lightninglike') || toCurrency.endsWith('lnurlpay') || this.lightning) {
|
||||
return "ln";
|
||||
} else if (toCurrency.endsWith('LN') || toCurrency.endsWith('LNURL')) {
|
||||
return null;
|
||||
} else {
|
||||
return toCurrency.replace('_btclike', '').replace('_monerolike', '').replace('_zcashlike', '').toLowerCase();
|
||||
return toCurrency.replace('-CHAIN', '').replace('_CHAIN', '').toLowerCase();
|
||||
}
|
||||
},
|
||||
type () {
|
||||
@@ -96,16 +87,19 @@
|
||||
amountDue () {
|
||||
return this.model.isUnsetTopUp
|
||||
? undefined
|
||||
: this.model.btcDue * (1 + (@settings.AmountMarkupPercentage / 100));
|
||||
: this.model.due * (1 + (@settings.AmountMarkupPercentage / 100));
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
openDialog () {
|
||||
if (!this.settleMethodId){
|
||||
return;
|
||||
}
|
||||
window.__SIDESHIFT__ = {
|
||||
parentAffiliateId: "qg0OrfHJV",
|
||||
defaultDepositMethodId: this.explicitId || undefined,
|
||||
defaultSettleMethodId: this.settleMethodId,
|
||||
settleAddress: this.lightning || this.model.btcAddress,
|
||||
settleAddress: this.model.address,
|
||||
settleAmount: this.amountDue,
|
||||
type: this.type
|
||||
};
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
@using BTCPayServer.Plugins.SideShift
|
||||
@inject SideShiftService SideShiftService
|
||||
@model BTCPayServer.Models.InvoicingModels.PaymentModel
|
||||
@model BTCPayServer.Models.InvoicingModels.CheckoutModel
|
||||
@{
|
||||
const string id = "SideShift";
|
||||
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
|
||||
@inject SideShiftService SideShiftService
|
||||
@{
|
||||
@@ -14,7 +15,8 @@
|
||||
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())
|
||||
{
|
||||
<script>
|
||||
@@ -26,7 +28,7 @@
|
||||
memo = tuple.HasMemo,
|
||||
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 => {
|
||||
const ssButton = document.createElement("button");
|
||||
ssButton.type= "button";
|
||||
@@ -142,7 +144,7 @@
|
||||
<select id="sspmi" class="form-select">
|
||||
@foreach (var opt in potentialPaymentMethods)
|
||||
{
|
||||
<option value="@opt.ToString()">@opt.ToPrettyString()</option>
|
||||
<option value="@opt.ToString()">@opt.ToString()</option>
|
||||
}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
@@ -4,13 +4,14 @@
|
||||
@using BTCPayServer.Plugins.SideShift
|
||||
@using Microsoft.AspNetCore.Mvc.TagHelpers
|
||||
@model BTCPayServer.Plugins.SideShift.SideShiftSettings
|
||||
@inject BTCPayNetworkProvider BTCPayNetworkProvider
|
||||
@inject SideShiftService SideShiftService
|
||||
@{
|
||||
ViewData.SetActivePage("SideShift", "SideShift", "SideShift");
|
||||
var store = Context.GetStoreData();
|
||||
var allowedPaymentMethods = store.GetEnabledPaymentIds(BTCPayNetworkProvider)
|
||||
.Select(pmi => new SelectListItem(pmi.ToPrettyString(), pmi.ToString()))
|
||||
var allowedPaymentMethods = store.GetEnabledPaymentIds()
|
||||
.Where(id => !id.ToString().EndsWith("LN") && !id.ToString().EndsWith("LNURL"))
|
||||
.Select(pmi => new SelectListItem(pmi.ToString(), pmi.ToString()))
|
||||
|
||||
.Prepend(new SelectListItem("Any", ""));
|
||||
var coins = await SideShiftService.GetDepositOptions();
|
||||
var allowedCoins = coins.OrderBy(coin => coin.ToString()).Select(c => new SelectListItem(c.ToString(), $"{c.CryptoCode}_{c.Network}"));
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
<PropertyGroup>
|
||||
<Product>Subscriptions</Product>
|
||||
<Description>Offer and manage subscriptions through BTCPay Server</Description>
|
||||
<Version>1.0.1</Version>
|
||||
<Version>1.0.2</Version>
|
||||
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
|
||||
</PropertyGroup>
|
||||
<!-- Plugin development properties -->
|
||||
|
||||
@@ -1,14 +1,13 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using BTCPayServer;
|
||||
using BTCPayServer.Abstractions.Constants;
|
||||
using BTCPayServer.Abstractions.Extensions;
|
||||
using BTCPayServer.Client;
|
||||
using BTCPayServer.Client.Models;
|
||||
using BTCPayServer.Data;
|
||||
using BTCPayServer.Models;
|
||||
using BTCPayServer.Plugins.Subscriptions;
|
||||
using BTCPayServer.Services;
|
||||
using BTCPayServer.Services.Apps;
|
||||
using BTCPayServer.Services.PaymentRequests;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
@@ -23,13 +22,16 @@ namespace BTCPayServer.Plugins.Subscriptions;
|
||||
public class SubscriptionController : Controller
|
||||
{
|
||||
private readonly AppService _appService;
|
||||
private readonly UriResolver _uriResolver;
|
||||
private readonly PaymentRequestRepository _paymentRequestRepository;
|
||||
private readonly SubscriptionService _subscriptionService;
|
||||
|
||||
public SubscriptionController(AppService appService,
|
||||
UriResolver uriResolver,
|
||||
PaymentRequestRepository paymentRequestRepository, SubscriptionService subscriptionService)
|
||||
{
|
||||
_appService = appService;
|
||||
_uriResolver = uriResolver;
|
||||
_paymentRequestRepository = paymentRequestRepository;
|
||||
_subscriptionService = subscriptionService;
|
||||
}
|
||||
@@ -44,7 +46,7 @@ public class SubscriptionController : Controller
|
||||
return NotFound();
|
||||
var ss = app.GetSettings<SubscriptionAppSettings>();
|
||||
ss.SubscriptionName = app.Name;
|
||||
ViewData["StoreBranding"] = new StoreBrandingViewModel(app.StoreData.GetStoreBlob());
|
||||
ViewData["StoreBranding"] =await StoreBrandingViewModel.CreateAsync(Request, _uriResolver, app.StoreData.GetStoreBlob());
|
||||
return View(ss);
|
||||
}
|
||||
|
||||
@@ -62,8 +64,7 @@ public class SubscriptionController : Controller
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
|
||||
ViewData["StoreBranding"] = new StoreBrandingViewModel(app.StoreData.GetStoreBlob());
|
||||
ViewData["StoreBranding"] =await StoreBrandingViewModel.CreateAsync(Request, _uriResolver, app.StoreData.GetStoreBlob());
|
||||
|
||||
return View(ss);
|
||||
}
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
using BTCPayServer.Abstractions.Contracts;
|
||||
using BTCPayServer.Abstractions.Extensions;
|
||||
using BTCPayServer.Abstractions.Models;
|
||||
using BTCPayServer.Abstractions.Services;
|
||||
using BTCPayServer.HostedServices.Webhooks;
|
||||
using BTCPayServer.Services;
|
||||
using BTCPayServer.Services.Apps;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
@@ -18,12 +16,11 @@ namespace BTCPayServer.Plugins.Subscriptions
|
||||
{
|
||||
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)
|
||||
{
|
||||
|
||||
applicationBuilder.AddSingleton<ISwaggerProvider, SubscriptionsSwaggerProvider>();
|
||||
applicationBuilder.AddSingleton<SubscriptionService>();
|
||||
applicationBuilder.AddSingleton<IWebhookProvider>(o => o.GetRequiredService<SubscriptionService>());
|
||||
@@ -35,19 +32,17 @@ namespace BTCPayServer.Plugins.Subscriptions
|
||||
}
|
||||
}
|
||||
|
||||
public class SubscriptionsSwaggerProvider: ISwaggerProvider
|
||||
public class SubscriptionsSwaggerProvider : ISwaggerProvider
|
||||
{
|
||||
private readonly IFileProvider _fileProvider;
|
||||
|
||||
public SubscriptionsSwaggerProvider(IWebHostEnvironment webHostEnvironment)
|
||||
{
|
||||
|
||||
_fileProvider = webHostEnvironment.WebRootFileProvider;
|
||||
}
|
||||
|
||||
public async Task<JObject> Fetch()
|
||||
{
|
||||
|
||||
var file = _fileProvider.GetFileInfo("Resources/swagger.subscriptions.json");
|
||||
using var reader = new StreamReader(file.CreateReadStream());
|
||||
return JObject.Parse(await reader.ReadToEndAsync());
|
||||
|
||||
@@ -48,10 +48,10 @@ public class AppMigrate : IStartupTask
|
||||
await using var ctx = _contextFactory.CreateContext();
|
||||
var invoices = await ctx.Invoices
|
||||
.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)
|
||||
{
|
||||
var entity = invoice.GetBlob(_btcPayNetworkProvider);
|
||||
var entity = invoice.GetBlob();
|
||||
entity.Metadata.SetAdditionalData("appId", app.Id);
|
||||
entity.InternalTags.Add(AppService.GetAppInternalTag(app.Id));
|
||||
InvoiceRepository.AddToTextSearch(ctx, invoice, AppService.GetAppSearchTerm(app) );
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
<PropertyGroup>
|
||||
<Product>TicketTailor</Product>
|
||||
<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>
|
||||
</PropertyGroup>
|
||||
<!-- Plugin development properties -->
|
||||
|
||||
@@ -12,6 +12,7 @@ using BTCPayServer.Client.Models;
|
||||
using BTCPayServer.Controllers;
|
||||
using BTCPayServer.Data;
|
||||
using BTCPayServer.Models;
|
||||
using BTCPayServer.Services;
|
||||
using BTCPayServer.Services.Apps;
|
||||
using BTCPayServer.Services.Invoices;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
@@ -28,6 +29,7 @@ namespace BTCPayServer.Plugins.TicketTailor
|
||||
{
|
||||
private readonly IHttpClientFactory _httpClientFactory;
|
||||
private readonly TicketTailorService _ticketTailorService;
|
||||
private readonly UriResolver _uriResolver;
|
||||
private readonly AppService _appService;
|
||||
private readonly ApplicationDbContextFactory _contextFactory;
|
||||
private readonly InvoiceRepository _invoiceRepository;
|
||||
@@ -35,6 +37,7 @@ namespace BTCPayServer.Plugins.TicketTailor
|
||||
|
||||
public TicketTailorController(IHttpClientFactory httpClientFactory,
|
||||
TicketTailorService ticketTailorService,
|
||||
UriResolver uriResolver,
|
||||
AppService appService,
|
||||
ApplicationDbContextFactory contextFactory,
|
||||
InvoiceRepository invoiceRepository,
|
||||
@@ -42,6 +45,7 @@ namespace BTCPayServer.Plugins.TicketTailor
|
||||
{
|
||||
_httpClientFactory = httpClientFactory;
|
||||
_ticketTailorService = ticketTailorService;
|
||||
_uriResolver = uriResolver;
|
||||
_appService = appService;
|
||||
_contextFactory = contextFactory;
|
||||
_invoiceRepository = invoiceRepository;
|
||||
@@ -87,7 +91,7 @@ namespace BTCPayServer.Plugins.TicketTailor
|
||||
return View(new TicketTailorViewModel()
|
||||
{
|
||||
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)},
|
||||
Checkout =
|
||||
{
|
||||
RequiresRefundEmail = true,
|
||||
RedirectAutomatically = price > 0,
|
||||
RedirectURL = redirectUrl,
|
||||
},
|
||||
@@ -292,13 +295,13 @@ namespace BTCPayServer.Plugins.TicketTailor
|
||||
|
||||
}, 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);
|
||||
}
|
||||
|
||||
return inv.Status.ToModernStatus() == InvoiceStatus.Settled
|
||||
return inv.Status == InvoiceStatus.Settled
|
||||
? RedirectToAction("Receipt", 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 result = new TicketReceiptPage() {InvoiceId = invoiceId};
|
||||
result.Status = inv.Status.ToModernStatus();
|
||||
result.Status = inv.Status;
|
||||
if (result.Status == InvoiceStatus.Settled &&
|
||||
inv.Metadata.AdditionalData.TryGetValue("ticketIds", out var ticketIds))
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ namespace BTCPayServer.Plugins.TicketTailor
|
||||
{
|
||||
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)
|
||||
|
||||
@@ -101,8 +101,7 @@ public class TicketTailorService : EventHostedServiceBase, IWebhookProvider
|
||||
!new[]
|
||||
{
|
||||
InvoiceStatus.Settled, InvoiceStatus.Expired, InvoiceStatus.Invalid
|
||||
}.Contains(invoiceEvent.Invoice.GetInvoiceState().Status
|
||||
.ToModernStatus()):
|
||||
}.Contains(invoiceEvent.Invoice.GetInvoiceState().Status):
|
||||
return;
|
||||
case InvoiceEvent invoiceEvent:
|
||||
|
||||
@@ -157,7 +156,7 @@ public class TicketTailorService : EventHostedServiceBase, IWebhookProvider
|
||||
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) &&
|
||||
@@ -178,7 +177,7 @@ public class TicketTailorService : EventHostedServiceBase, IWebhookProvider
|
||||
return;
|
||||
}
|
||||
|
||||
if (invoice.Status.ToModernStatus() != InvoiceStatus.Settled)
|
||||
if (invoice.Status != InvoiceStatus.Settled)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
<PropertyGroup>
|
||||
<Product>Coinjoin</Product>
|
||||
<Description>Allows you to integrate your btcpayserver store with coinjoins.</Description>
|
||||
<Version>1.0.100</Version>
|
||||
<Version>1.0.101</Version>
|
||||
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
|
||||
</PropertyGroup>
|
||||
|
||||
|
||||
@@ -11,7 +11,9 @@ using BTCPayServer.Data;
|
||||
using BTCPayServer.HostedServices;
|
||||
using BTCPayServer.Payments;
|
||||
using BTCPayServer.Payments.PayJoin;
|
||||
using BTCPayServer.Payouts;
|
||||
using BTCPayServer.Services;
|
||||
using BTCPayServer.Services.Invoices;
|
||||
using BTCPayServer.Services.Stores;
|
||||
using BTCPayServer.Services.Wallets;
|
||||
using LinqKit;
|
||||
@@ -37,12 +39,14 @@ using WalletWasabi.WabiSabi.Backend.Rounds;
|
||||
using WalletWasabi.WabiSabi.Client;
|
||||
using WalletWasabi.Wallets;
|
||||
using LogLevel = WalletWasabi.Logging.LogLevel;
|
||||
using SecureRandom = WalletWasabi.Crypto.Randomness.SecureRandom;
|
||||
|
||||
namespace BTCPayServer.Plugins.Wabisabi;
|
||||
|
||||
|
||||
public class BTCPayWallet : IWallet, IDestinationProvider
|
||||
{
|
||||
private readonly PaymentMethodHandlerDictionary _paymentMethodHandlerDictionary;
|
||||
private readonly WalletRepository _walletRepository;
|
||||
private readonly BTCPayNetworkProvider _btcPayNetworkProvider;
|
||||
private readonly BitcoinLikePayoutHandler _bitcoinLikePayoutHandler;
|
||||
@@ -56,6 +60,7 @@ public class BTCPayWallet : IWallet, IDestinationProvider
|
||||
public static readonly BlockchainAnalyzer BlockchainAnalyzer = new();
|
||||
|
||||
public BTCPayWallet(
|
||||
PaymentMethodHandlerDictionary paymentMethodHandlerDictionary,
|
||||
WalletRepository walletRepository,
|
||||
BTCPayNetworkProvider btcPayNetworkProvider,
|
||||
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)
|
||||
.ToArray()));
|
||||
KeyChain = keyChain;
|
||||
_paymentMethodHandlerDictionary = paymentMethodHandlerDictionary;
|
||||
_walletRepository = walletRepository;
|
||||
_btcPayNetworkProvider = btcPayNetworkProvider;
|
||||
_bitcoinLikePayoutHandler = bitcoinLikePayoutHandler;
|
||||
@@ -495,7 +501,7 @@ public class BTCPayWallet : IWallet, IDestinationProvider
|
||||
if (storeIdForutxo != StoreId)
|
||||
{
|
||||
var s = await _storeRepository.FindStore(storeIdForutxo);
|
||||
var scheme = s.GetDerivationSchemeSettings(_btcPayNetworkProvider, "BTC");
|
||||
var scheme = s.GetDerivationSchemeSettings(_paymentMethodHandlerDictionary, "BTC");
|
||||
utxoDerivationScheme = scheme.AccountDerivation;
|
||||
}
|
||||
|
||||
@@ -689,7 +695,7 @@ public async Task<IEnumerable<IDestination>> GetNextDestinationsAsync(int count,
|
||||
try
|
||||
{
|
||||
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())
|
||||
@@ -718,20 +724,19 @@ public async Task<IEnumerable<IDestination>> GetNextDestinationsAsync(int count,
|
||||
{
|
||||
States = new [] {PayoutState.AwaitingPayment},
|
||||
Stores = new []{StoreId},
|
||||
PaymentMethods = new []{"BTC"}
|
||||
PayoutMethods = new []{ PayoutTypes.CHAIN.GetPayoutMethodId("BTC").ToString()}
|
||||
})).Select(async data =>
|
||||
{
|
||||
|
||||
var claim = await _bitcoinLikePayoutHandler.ParseClaimDestination(new PaymentMethodId("BTC", BitcoinPaymentType.Instance),
|
||||
data.Destination, CancellationToken.None);
|
||||
var payoutBlob = data.GetBlob(_btcPayNetworkJsonSerializerSettings);
|
||||
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;
|
||||
}
|
||||
|
||||
var payoutBlob = data.GetBlob(_btcPayNetworkJsonSerializerSettings);
|
||||
var value = new Money(payoutBlob.CryptoAmount.Value, MoneyUnit.BTC);
|
||||
var value = new Money(data.Amount.Value, MoneyUnit.BTC);
|
||||
return new PendingPayment()
|
||||
{
|
||||
Identifier = data.Id,
|
||||
|
||||
@@ -5,6 +5,7 @@ using System.Net.Http;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using BTCPayServer.Services.Invoices;
|
||||
using BTCPayServer.Services.Stores;
|
||||
using BTCPayServer.Services.Wallets;
|
||||
using NBitcoin;
|
||||
@@ -17,16 +18,19 @@ public class WabisabiScriptResolver: WabiSabiConfig.CoordinatorScriptResolver
|
||||
{
|
||||
private readonly IHttpClientFactory _httpClientFactory;
|
||||
private readonly StoreRepository _storeRepository;
|
||||
private readonly PaymentMethodHandlerDictionary _paymentMethodHandlerDictionary;
|
||||
private readonly BTCPayNetworkProvider _networkProvider;
|
||||
private readonly BTCPayWalletProvider _walletProvider;
|
||||
|
||||
public WabisabiScriptResolver(IHttpClientFactory httpClientFactory,
|
||||
StoreRepository storeRepository,
|
||||
PaymentMethodHandlerDictionary paymentMethodHandlerDictionary,
|
||||
BTCPayNetworkProvider networkProvider,
|
||||
BTCPayWalletProvider walletProvider)
|
||||
{
|
||||
_httpClientFactory = httpClientFactory;
|
||||
_storeRepository = storeRepository;
|
||||
_paymentMethodHandlerDictionary = paymentMethodHandlerDictionary;
|
||||
_networkProvider = networkProvider;
|
||||
_walletProvider = walletProvider;
|
||||
}
|
||||
@@ -61,7 +65,7 @@ public class WabisabiScriptResolver: WabiSabiConfig.CoordinatorScriptResolver
|
||||
var store = await _storeRepository.FindStore(value);
|
||||
var cryptoCode = _networkProvider.GetAll().OfType<BTCPayNetwork>()
|
||||
.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 kpi = await w.ReserveAddressAsync(store.Id, dss.AccountDerivation, "wabisabi coordinator");
|
||||
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