This repository was archived by the owner on Mar 7, 2026. It is now read-only.
forked from btcpayserver/btcpayserver-plugin-template
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathFlashPlugin.cs
More file actions
238 lines (202 loc) · 12.4 KB
/
FlashPlugin.cs
File metadata and controls
238 lines (202 loc) · 12.4 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
#nullable enable
using System;
using System.Diagnostics;
using BTCPayServer.Abstractions.Contracts;
using BTCPayServer.Abstractions.Models;
using BTCPayServer.Abstractions.Services;
using BTCPayServer.Data;
using BTCPayServer.Lightning;
using BTCPayServer.Plugins.Flash.Services;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
namespace BTCPayServer.Plugins.Flash
{
public class FlashPlugin : BaseBTCPayServerPlugin
{
private ILogger<FlashPlugin>? _logger;
// Static constructor that will run when the class is loaded
static FlashPlugin()
{
// Use direct file system logging to diagnose issues
try
{
FlashPluginLogger.Log("FlashPlugin class is being loaded");
}
catch (Exception ex)
{
Console.WriteLine($"FLASH ERROR in static constructor: {ex.Message}");
}
}
public override string Identifier => "BTCPayServer.Plugins.Flash";
public override string Name => "Flash";
public override string Description => "Integration with Flash wallet featuring full LNURL, Lightning Address and Boltcard support.";
public override Version Version => new Version(1, 5, 2);
public override IBTCPayServerPlugin.PluginDependency[] Dependencies => new[]
{
new IBTCPayServerPlugin.PluginDependency { Identifier = "BTCPayServer", Condition = ">=2.0.0" }
};
public override void Execute(IServiceCollection applicationBuilder)
{
try
{
FlashPluginLogger.Log("Execute method called");
// Create a service provider for initialization only
// This is safer than building the entire service collection which might not be ready
var serviceProvider = applicationBuilder.BuildServiceProvider(new ServiceProviderOptions { ValidateOnBuild = false, ValidateScopes = false });
var loggerFactory = serviceProvider.GetService<ILoggerFactory>();
_logger = loggerFactory?.CreateLogger<FlashPlugin>();
_logger?.LogInformation("Flash Plugin: Starting plugin initialization");
FlashPluginLogger.Log("Got logger service");
// UI extensions temporarily removed for rebuild
_logger?.LogInformation("Flash Plugin: UI extensions disabled for rebuild");
FlashPluginLogger.Log("UI extensions disabled for rebuild");
// Register the Flash Lightning client service
applicationBuilder.AddSingleton<FlashLightningConnectionStringHandler>();
applicationBuilder.AddSingleton<ILightningConnectionStringHandler>(provider => provider.GetRequiredService<FlashLightningConnectionStringHandler>());
// Register WebSocket service for real-time updates
applicationBuilder.AddScoped<IFlashWebSocketService, FlashWebSocketService>();
// Register core services
applicationBuilder.AddScoped<IFlashGraphQLService, FlashGraphQLService>();
applicationBuilder.AddScoped<IFlashInvoiceService, FlashInvoiceService>();
applicationBuilder.AddScoped<IFlashExchangeRateService, FlashExchangeRateService>();
applicationBuilder.AddScoped<IFlashBoltcardService, FlashBoltcardService>();
applicationBuilder.AddScoped<IFlashTransactionService, FlashTransactionService>();
applicationBuilder.AddScoped<IFlashWalletService, FlashWalletService>();
applicationBuilder.AddScoped<IFlashMonitoringService, FlashMonitoringService>();
applicationBuilder.AddScoped<IFlashPaymentService>(provider =>
new FlashPaymentService(
provider.GetRequiredService<IFlashGraphQLService>(),
provider.GetRequiredService<IFlashExchangeRateService>(),
provider.GetRequiredService<ILogger<FlashPaymentService>>(),
provider
));
applicationBuilder.AddHostedService<BoltcardInvoicePoller>();
// Register payout tracking services and database
applicationBuilder.AddDbContext<Data.FlashPluginDbContext>((provider, options) =>
{
// Get the database context factory from BTCPay Server
var dbContextFactory = provider.GetService<ApplicationDbContextFactory>();
if (dbContextFactory != null)
{
// Use the same database configuration as BTCPay Server
dbContextFactory.ConfigureBuilder(options);
}
else
{
// Fallback to in-memory database for development/testing
options.UseInMemoryDatabase("FlashPlugin");
_logger?.LogWarning("Using in-memory database for Flash plugin - this is not recommended for production");
}
});
applicationBuilder.AddScoped<Data.FlashPayoutRepository>();
applicationBuilder.AddScoped<IFlashPayoutTrackingService, FlashPayoutTrackingService>();
applicationBuilder.AddHostedService<Data.FlashPluginMigrationRunner>();
// Register FlashLightningClient with a factory method that creates it when needed
// The factory will use IServiceProvider to get other dependencies like loggers
applicationBuilder.AddScoped<FlashLightningClient>(provider =>
{
var loggerFactory = provider.GetRequiredService<ILoggerFactory>();
var logger = loggerFactory.CreateLogger<FlashLightningClient>();
try
{
// NOTE: This factory is only used for dependency injection registration
// The actual client instances are created by FlashLightningConnectionStringHandler
// with proper authentication tokens from the connection string
logger.LogWarning("FlashLightningClient factory method called - this should only happen during DI registration");
// Return null - the actual clients will be created by the connection string handler
return null;
}
catch (Exception ex)
{
logger.LogError(ex, "Error in FlashLightningClient factory method");
throw;
}
});
_logger?.LogInformation("Flash Plugin: Registered Lightning services");
FlashPluginLogger.Log("Registered Lightning services");
// Register the Pull Payment handler services
applicationBuilder.AddScoped<Models.FlashPullPaymentHandler>(provider =>
{
var logger = provider.GetRequiredService<ILoggerFactory>().CreateLogger<Models.FlashPullPaymentHandler>();
var flashClient = provider.GetService<FlashLightningClient>();
return new Models.FlashPullPaymentHandler(logger, flashClient);
});
// Register plugin hook filters for Pull Payment support with factory methods
// 1. PullPaymentDestinationValidator
applicationBuilder.AddScoped<Models.PullPaymentDestinationValidator>(provider =>
{
var logger = provider.GetRequiredService<ILoggerFactory>().CreateLogger<Models.PullPaymentDestinationValidator>();
return new Models.PullPaymentDestinationValidator(logger);
});
applicationBuilder.AddScoped<IPluginHookFilter>(provider =>
provider.GetRequiredService<Models.PullPaymentDestinationValidator>());
// 2. PullPaymentClaimProcessor
applicationBuilder.AddScoped<Models.PullPaymentClaimProcessor>(provider =>
{
var logger = provider.GetRequiredService<ILoggerFactory>().CreateLogger<Models.PullPaymentClaimProcessor>();
var flashClient = provider.GetService<FlashLightningClient>();
return new Models.PullPaymentClaimProcessor(logger, flashClient, provider);
});
applicationBuilder.AddScoped<IPluginHookFilter>(provider =>
provider.GetRequiredService<Models.PullPaymentClaimProcessor>());
// 3. Regular LnurlWithdrawHandler
applicationBuilder.AddScoped<Models.LnurlWithdrawHandler>(provider =>
{
var logger = provider.GetRequiredService<ILoggerFactory>().CreateLogger<Models.LnurlWithdrawHandler>();
var flashClient = provider.GetService<FlashLightningClient>();
var pullPaymentHandler = provider.GetService<Models.FlashPullPaymentHandler>();
return new Models.LnurlWithdrawHandler(logger, flashClient, pullPaymentHandler);
});
applicationBuilder.AddScoped<IPluginHookFilter>(provider =>
provider.GetRequiredService<Models.LnurlWithdrawHandler>());
// 4. Boltcard patch for amount verification
applicationBuilder.AddScoped<Models.BoltcardPatch>(provider =>
{
var logger = provider.GetRequiredService<ILoggerFactory>().CreateLogger<Models.BoltcardPatch>();
return new Models.BoltcardPatch(logger);
});
applicationBuilder.AddScoped<IPluginHookFilter>(provider =>
provider.GetRequiredService<Models.BoltcardPatch>());
// 5. Boltcard invoice tracker for payment detection
applicationBuilder.AddScoped<Models.BoltcardInvoiceTracker>(provider =>
{
var logger = provider.GetRequiredService<ILoggerFactory>().CreateLogger<Models.BoltcardInvoiceTracker>();
return new Models.BoltcardInvoiceTracker(logger, provider);
});
applicationBuilder.AddScoped<IPluginHookFilter>(provider =>
provider.GetRequiredService<Models.BoltcardInvoiceTracker>());
// 6. Payout event listeners for tracking
applicationBuilder.AddScoped<Models.PayoutEventListener>();
applicationBuilder.AddScoped<IPluginHookFilter>(provider =>
provider.GetRequiredService<Models.PayoutEventListener>());
applicationBuilder.AddScoped<Models.PayoutStateChangeListener>();
applicationBuilder.AddScoped<IPluginHookFilter>(provider =>
provider.GetRequiredService<Models.PayoutStateChangeListener>());
_logger?.LogInformation("Flash Plugin: Registered Pull Payment handlers");
FlashPluginLogger.Log("Registered Pull Payment handlers");
// Controllers temporarily removed for UI rebuild
applicationBuilder.AddSingleton<FlashPlugin>(this);
_logger?.LogInformation("Flash Plugin: Controllers disabled for UI rebuild");
FlashPluginLogger.Log("Controllers disabled for UI rebuild");
base.Execute(applicationBuilder);
_logger?.LogInformation("Flash Plugin: Initialization completed successfully");
FlashPluginLogger.Log("Initialization completed successfully");
}
catch (Exception ex)
{
// Log to file system first
FlashPluginLogger.Log($"ERROR: {ex.Message}\n{ex.StackTrace}");
// Use proper logging instead of console output
// Also try standard Debug output
Debug.WriteLine($"Flash Plugin ERROR: {ex.Message}");
Debug.WriteLine($"Flash Plugin ERROR: {ex.StackTrace}");
if (_logger != null)
{
_logger.LogError(ex, "Flash Plugin: Error during plugin initialization");
}
throw; // Rethrow to let BTCPay Server handle it
}
}
}
}