968 lines
36 KiB
C#
968 lines
36 KiB
C#
using BTCPayApp.Core.Auth;
|
|
using BTCPayApp.Core.Models;
|
|
using BTCPayApp.UI.Util;
|
|
using BTCPayServer.Client.Models;
|
|
using Fluxor;
|
|
|
|
namespace BTCPayApp.UI.Features;
|
|
|
|
[FeatureState]
|
|
public record StoreState
|
|
{
|
|
public AppUserStoreInfo? StoreInfo;
|
|
public RemoteData<StoreData>? Store;
|
|
public RemoteData<OnChainWalletOverviewData>? OnchainBalance;
|
|
public RemoteData<HistogramData>? OnchainHistogram;
|
|
public RemoteData<LightningNodeBalanceData>? LightningBalance;
|
|
public RemoteData<HistogramData>? LightningHistogram;
|
|
public RemoteData<PointOfSaleAppData>? PointOfSale;
|
|
public RemoteData<AppSalesStats>? PosSalesStats;
|
|
public RemoteData<List<AppItemStats>>? PosItemStats;
|
|
public RemoteData<IEnumerable<StoreRateResult>>? Rates;
|
|
public RemoteData<IEnumerable<InvoiceData>>? Invoices;
|
|
public RemoteData<IEnumerable<StoreUserData>>? Users;
|
|
public RemoteData<IEnumerable<RoleData>>? Roles;
|
|
public RemoteData<IEnumerable<NotificationData>>? Notifications;
|
|
private IDictionary<string,RemoteData<InvoiceData>?> _invoicesById = new Dictionary<string, RemoteData<InvoiceData>?>();
|
|
private IDictionary<string,RemoteData<InvoicePaymentMethodDataModel[]>?> _invoicePaymentMethodsById = new Dictionary<string, RemoteData<InvoicePaymentMethodDataModel[]>?>();
|
|
public HistogramData? UnifiedHistogram;
|
|
public HistogramType? HistogramType;
|
|
|
|
private static readonly string[] BitcoinUnits = [CurrencyDisplay.BTC, CurrencyDisplay.SATS];
|
|
|
|
public record SetStoreInfo(AppUserStoreInfo? StoreInfo);
|
|
public record SetHistogramType(HistogramType Type);
|
|
public record FetchStore(string StoreId);
|
|
public record FetchOnchainBalance(string StoreId);
|
|
public record FetchLightningBalance(string StoreId);
|
|
public record FetchOnchainHistogram(string StoreId, HistogramType? Type = null);
|
|
public record FetchLightningHistogram(string StoreId, HistogramType? Type = null);
|
|
public record FetchHistograms(string StoreId, HistogramType? Type = null);
|
|
public record FetchBalances(string StoreId, HistogramType? Type = null);
|
|
public record FetchNotifications(string StoreId);
|
|
public record UpdateNotification(string NotificationId, bool Seen);
|
|
public record SetNotification(NotificationData? Notification, string? Error);
|
|
public record FetchRoles(string StoreId);
|
|
public record FetchUsers(string StoreId);
|
|
public record FetchInvoices(string StoreId);
|
|
public record FetchInvoice(string StoreId, string InvoiceId);
|
|
public record FetchInvoicePaymentMethods(string StoreId, string InvoiceId);
|
|
public record FetchRates(AppUserStoreInfo Store);
|
|
public record FetchPointOfSale(string AppId);
|
|
public record FetchPointOfSaleStats(string AppId);
|
|
public record FetchPosItemStats(string AppId);
|
|
public record FetchPosSalesStats(string AppId);
|
|
public record UpdateStore(string StoreId, UpdateStoreRequest Request);
|
|
public record UpdatedStore(StoreData? Store, string? Error) : SetStore(Store, Error);
|
|
public record UpdatePointOfSale(string AppId, PointOfSaleAppRequest Request);
|
|
public record SetStore(StoreData? Store, string? Error);
|
|
public record SetOnchainBalance(OnChainWalletOverviewData? Overview, string? Error);
|
|
public record SetLightningBalance(LightningNodeBalanceData? Balance, string? Error);
|
|
public record SetOnchainHistogram(HistogramData? Data, string? Error);
|
|
public record SetLightningHistogram(HistogramData? Data, string? Error);
|
|
public record SetRoles(IEnumerable<RoleData>? Roles, string? Error);
|
|
public record SetUsers(IEnumerable<StoreUserData>? Users, string? Error);
|
|
public record SetNotifications(IEnumerable<NotificationData>? Notifications, string? Error);
|
|
public record SetInvoices(IEnumerable<InvoiceData>? Invoices, string? Error);
|
|
public record SetInvoice(InvoiceData? Invoice, string? Error, string InvoiceId);
|
|
public record SetInvoicePaymentMethods(InvoicePaymentMethodDataModel[]? PaymentMethods, string? Error, string InvoiceId);
|
|
public record SetRates(IEnumerable<StoreRateResult>? Rates, string? Error);
|
|
public record SetPointOfSale(PointOfSaleAppData? AppData, string? Error);
|
|
public record UpdatedPointOfSale(PointOfSaleAppData? AppData, string? Error) : SetPointOfSale(AppData, Error);
|
|
public record SetPosItemStats(List<AppItemStats>? ItemStats, string? Error);
|
|
public record SetPosSalesStats(AppSalesStats? SalesStats, string? Error);
|
|
public record RefreshStore(AppUserStoreInfo Store);
|
|
|
|
protected class SetStoreInfoReducer : Reducer<StoreState, SetStoreInfo>
|
|
{
|
|
public override StoreState Reduce(StoreState state, SetStoreInfo action)
|
|
{
|
|
return state with
|
|
{
|
|
StoreInfo = action.StoreInfo,
|
|
Store = new RemoteData<StoreData>(),
|
|
OnchainBalance = new RemoteData<OnChainWalletOverviewData>(),
|
|
LightningBalance = new RemoteData<LightningNodeBalanceData>(),
|
|
OnchainHistogram = new RemoteData<HistogramData>(),
|
|
LightningHistogram = new RemoteData<HistogramData>(),
|
|
PointOfSale = new RemoteData<PointOfSaleAppData>(),
|
|
PosItemStats = new RemoteData<List<AppItemStats>>(),
|
|
PosSalesStats = new RemoteData<AppSalesStats>(),
|
|
Rates = new RemoteData<IEnumerable<StoreRateResult>>(),
|
|
Invoices = new RemoteData<IEnumerable<InvoiceData>>(),
|
|
Notifications = new RemoteData<IEnumerable<NotificationData>>(),
|
|
_invoicesById = new Dictionary<string, RemoteData<InvoiceData>?>(),
|
|
_invoicePaymentMethodsById = new Dictionary<string, RemoteData<InvoicePaymentMethodDataModel[]>?>(),
|
|
UnifiedHistogram = null,
|
|
HistogramType = null
|
|
};
|
|
}
|
|
}
|
|
|
|
|
|
protected class SetHistogramTypeReducer : Reducer<StoreState, SetHistogramType>
|
|
{
|
|
public override StoreState Reduce(StoreState state, SetHistogramType action)
|
|
{
|
|
return state with
|
|
{
|
|
HistogramType = action.Type,
|
|
};
|
|
}
|
|
}
|
|
|
|
protected class FetchStoreReducer : Reducer<StoreState, FetchStore>
|
|
{
|
|
public override StoreState Reduce(StoreState state, FetchStore action)
|
|
{
|
|
return state with
|
|
{
|
|
Store = (state.Store ?? new RemoteData<StoreData>()) with
|
|
{
|
|
Loading = true
|
|
}
|
|
};
|
|
}
|
|
}
|
|
|
|
protected class FetchOnchainBalanceReducer : Reducer<StoreState, FetchOnchainBalance>
|
|
{
|
|
public override StoreState Reduce(StoreState state, FetchOnchainBalance action)
|
|
{
|
|
return state with
|
|
{
|
|
OnchainBalance = (state.OnchainBalance ?? new RemoteData<OnChainWalletOverviewData>()) with
|
|
{
|
|
Loading = true
|
|
}
|
|
};
|
|
}
|
|
}
|
|
|
|
protected class FetchLightningBalanceReducer : Reducer<StoreState, FetchLightningBalance>
|
|
{
|
|
public override StoreState Reduce(StoreState state, FetchLightningBalance action)
|
|
{
|
|
return state with
|
|
{
|
|
LightningBalance = (state.LightningBalance ?? new RemoteData<LightningNodeBalanceData>()) with
|
|
{
|
|
Loading = true
|
|
}
|
|
};
|
|
}
|
|
}
|
|
|
|
protected class FetchRolesReducer : Reducer<StoreState, FetchRoles>
|
|
{
|
|
public override StoreState Reduce(StoreState state, FetchRoles action)
|
|
{
|
|
return state with
|
|
{
|
|
Roles = (state.Roles ?? new RemoteData<IEnumerable<RoleData>>()) with
|
|
{
|
|
Loading = true
|
|
}
|
|
};
|
|
}
|
|
}
|
|
|
|
protected class FetchUsersReducer : Reducer<StoreState, FetchUsers>
|
|
{
|
|
public override StoreState Reduce(StoreState state, FetchUsers action)
|
|
{
|
|
return state with
|
|
{
|
|
Users = (state.Users ?? new RemoteData<IEnumerable<StoreUserData>>()) with
|
|
{
|
|
Loading = true
|
|
}
|
|
};
|
|
}
|
|
}
|
|
|
|
protected class FetchNotificationsReducer : Reducer<StoreState, FetchNotifications>
|
|
{
|
|
public override StoreState Reduce(StoreState state, FetchNotifications action)
|
|
{
|
|
return state with
|
|
{
|
|
Notifications = (state.Notifications ?? new RemoteData<IEnumerable<NotificationData>>()) with
|
|
{
|
|
Loading = true
|
|
}
|
|
};
|
|
}
|
|
}
|
|
|
|
protected class FetchInvoicesReducer : Reducer<StoreState, FetchInvoices>
|
|
{
|
|
public override StoreState Reduce(StoreState state, FetchInvoices action)
|
|
{
|
|
return state with
|
|
{
|
|
Invoices = (state.Invoices ?? new RemoteData<IEnumerable<InvoiceData>>()) with
|
|
{
|
|
Loading = true
|
|
}
|
|
};
|
|
}
|
|
}
|
|
|
|
protected class FetchInvoiceReducer : Reducer<StoreState, FetchInvoice>
|
|
{
|
|
public override StoreState Reduce(StoreState state, FetchInvoice action)
|
|
{
|
|
var invoice = GetInvoice(state, action.InvoiceId)?.Data;
|
|
if (state._invoicesById.ContainsKey(action.InvoiceId))
|
|
state._invoicesById.Remove(action.InvoiceId);
|
|
return state with
|
|
{
|
|
_invoicesById = new Dictionary<string, RemoteData<InvoiceData>?>(state._invoicesById)
|
|
{
|
|
{ action.InvoiceId, new RemoteData<InvoiceData>(invoice, null, true) }
|
|
}
|
|
};
|
|
}
|
|
}
|
|
|
|
protected class FetchInvoicePaymentMethodsReducer : Reducer<StoreState, FetchInvoicePaymentMethods>
|
|
{
|
|
public override StoreState Reduce(StoreState state, FetchInvoicePaymentMethods action)
|
|
{
|
|
var pms = GetInvoicePaymentMethods(state, action.InvoiceId)?.Data;
|
|
if (state._invoicePaymentMethodsById.ContainsKey(action.InvoiceId))
|
|
state._invoicePaymentMethodsById.Remove(action.InvoiceId);
|
|
return state with
|
|
{
|
|
_invoicePaymentMethodsById = new Dictionary<string, RemoteData<InvoicePaymentMethodDataModel[]>?>(state._invoicePaymentMethodsById)
|
|
{
|
|
{ action.InvoiceId, new RemoteData<InvoicePaymentMethodDataModel[]>(pms, null, true) }
|
|
}
|
|
};
|
|
}
|
|
}
|
|
|
|
protected class FetchRatesReducer : Reducer<StoreState, FetchRates>
|
|
{
|
|
public override StoreState Reduce(StoreState state, FetchRates action)
|
|
{
|
|
return state with
|
|
{
|
|
Rates = (state.Rates ?? new RemoteData<IEnumerable<StoreRateResult>>()) with
|
|
{
|
|
Loading = true
|
|
}
|
|
};
|
|
}
|
|
}
|
|
|
|
protected class FetchPointOfSaleReducer : Reducer<StoreState, FetchPointOfSale>
|
|
{
|
|
public override StoreState Reduce(StoreState state, FetchPointOfSale action)
|
|
{
|
|
return state with
|
|
{
|
|
PointOfSale = (state.PointOfSale ?? new RemoteData<PointOfSaleAppData>()) with
|
|
{
|
|
Loading = true
|
|
}
|
|
};
|
|
}
|
|
}
|
|
|
|
protected class FetchPointOfSaleStatsReducer : Reducer<StoreState, FetchPointOfSaleStats>
|
|
{
|
|
public override StoreState Reduce(StoreState state, FetchPointOfSaleStats action)
|
|
{
|
|
return state with
|
|
{
|
|
PosItemStats = (state.PosItemStats ?? new RemoteData<List<AppItemStats>>()) with
|
|
{
|
|
Loading = true
|
|
},
|
|
PosSalesStats = (state.PosSalesStats ?? new RemoteData<AppSalesStats>()) with
|
|
{
|
|
Loading = true
|
|
}
|
|
};
|
|
}
|
|
}
|
|
|
|
protected class SetStoreReducer : Reducer<StoreState, SetStore>
|
|
{
|
|
public override StoreState Reduce(StoreState state, SetStore action)
|
|
{
|
|
return state with
|
|
{
|
|
Store = (state.Store ?? new RemoteData<StoreData>()) with {
|
|
Data = action.Store ?? state.Store?.Data,
|
|
Error = action.Error,
|
|
Loading = false,
|
|
Sending = false
|
|
}
|
|
};
|
|
}
|
|
}
|
|
|
|
protected class UpdateStoreReducer : Reducer<StoreState, UpdateStore>
|
|
{
|
|
public override StoreState Reduce(StoreState state, UpdateStore action)
|
|
{
|
|
return state with
|
|
{
|
|
Store = (state.Store ?? new RemoteData<StoreData>()) with
|
|
{
|
|
Sending = true
|
|
}
|
|
};
|
|
}
|
|
}
|
|
|
|
protected class SetOnchainBalanceReducer : Reducer<StoreState, SetOnchainBalance>
|
|
{
|
|
public override StoreState Reduce(StoreState state, SetOnchainBalance action)
|
|
{
|
|
return state with
|
|
{
|
|
OnchainBalance = (state.OnchainBalance ?? new RemoteData<OnChainWalletOverviewData>()) with {
|
|
Data = action.Overview ?? state.OnchainBalance?.Data,
|
|
Error = action.Error,
|
|
Loading = false,
|
|
Sending = false
|
|
}
|
|
};
|
|
}
|
|
}
|
|
|
|
protected class SetLightningBalanceReducer : Reducer<StoreState, SetLightningBalance>
|
|
{
|
|
public override StoreState Reduce(StoreState state, SetLightningBalance action)
|
|
{
|
|
return state with
|
|
{
|
|
LightningBalance = (state.LightningBalance ?? new RemoteData<LightningNodeBalanceData>()) with {
|
|
Data = action.Balance ?? state.LightningBalance?.Data,
|
|
Error = action.Error,
|
|
Loading = false,
|
|
Sending = false
|
|
}
|
|
};
|
|
}
|
|
}
|
|
|
|
protected class SetOnchainHistogramReducer : Reducer<StoreState, SetOnchainHistogram>
|
|
{
|
|
public override StoreState Reduce(StoreState state, SetOnchainHistogram action)
|
|
{
|
|
var data = action.Data ?? state.OnchainHistogram?.Data;
|
|
return state with
|
|
{
|
|
OnchainHistogram = (state.OnchainHistogram ?? new RemoteData<HistogramData>()) with {
|
|
Data = data,
|
|
Error = action.Error,
|
|
Loading = false,
|
|
Sending = false
|
|
},
|
|
UnifiedHistogram = GetUnifiedHistogram(data, state.LightningHistogram?.Data)
|
|
};
|
|
}
|
|
}
|
|
|
|
protected class SetLightningHistogramReducer : Reducer<StoreState, SetLightningHistogram>
|
|
{
|
|
public override StoreState Reduce(StoreState state, SetLightningHistogram action)
|
|
{
|
|
var data = action.Data ?? state.LightningHistogram?.Data;
|
|
return state with
|
|
{
|
|
LightningHistogram = (state.LightningHistogram ?? new RemoteData<HistogramData>()) with {
|
|
Data = data,
|
|
Error = action.Error,
|
|
Loading = false,
|
|
Sending = false
|
|
},
|
|
UnifiedHistogram = GetUnifiedHistogram(state.OnchainHistogram?.Data, data)
|
|
};
|
|
}
|
|
}
|
|
|
|
protected class SetRolesReducer : Reducer<StoreState, SetRoles>
|
|
{
|
|
public override StoreState Reduce(StoreState state, SetRoles action)
|
|
{
|
|
return state with
|
|
{
|
|
Roles = (state.Roles ?? new RemoteData<IEnumerable<RoleData>>()) with
|
|
{
|
|
Data = action.Roles,
|
|
Error = action.Error,
|
|
Loading = false
|
|
}
|
|
};
|
|
}
|
|
}
|
|
|
|
protected class SetUsersReducer : Reducer<StoreState, SetUsers>
|
|
{
|
|
public override StoreState Reduce(StoreState state, SetUsers action)
|
|
{
|
|
return state with
|
|
{
|
|
Users = (state.Users ?? new RemoteData<IEnumerable<StoreUserData>>()) with
|
|
{
|
|
Data = action.Users,
|
|
Error = action.Error,
|
|
Loading = false
|
|
}
|
|
};
|
|
}
|
|
}
|
|
|
|
protected class SetNotificationsReducer : Reducer<StoreState, SetNotifications>
|
|
{
|
|
public override StoreState Reduce(StoreState state, SetNotifications action)
|
|
{
|
|
return state with
|
|
{
|
|
Notifications = (state.Notifications ?? new RemoteData<IEnumerable<NotificationData>>()) with
|
|
{
|
|
Data = action.Notifications,
|
|
Error = action.Error,
|
|
Loading = false
|
|
}
|
|
};
|
|
}
|
|
}
|
|
|
|
protected class SetNotificationReducer : Reducer<StoreState, SetNotification>
|
|
{
|
|
public override StoreState Reduce(StoreState state, SetNotification action)
|
|
{
|
|
if (state.Notifications?.Data == null || action.Notification == null) return state;
|
|
return state with
|
|
{
|
|
Notifications = state.Notifications with
|
|
{
|
|
Data = state.Notifications.Data.Select(n =>
|
|
n.Id == action.Notification.Id ? action.Notification : n)
|
|
}
|
|
};
|
|
}
|
|
}
|
|
|
|
protected class SetInvoicesReducer : Reducer<StoreState, SetInvoices>
|
|
{
|
|
public override StoreState Reduce(StoreState state, SetInvoices action)
|
|
{
|
|
return state with
|
|
{
|
|
Invoices = (state.Invoices ?? new RemoteData<IEnumerable<InvoiceData>>()) with
|
|
{
|
|
Data = action.Invoices ?? state.Invoices?.Data,
|
|
Error = action.Error,
|
|
Loading = false
|
|
}
|
|
};
|
|
}
|
|
}
|
|
|
|
protected class SetInvoiceReducer : Reducer<StoreState, SetInvoice>
|
|
{
|
|
public override StoreState Reduce(StoreState state, SetInvoice action)
|
|
{
|
|
var invoice = action.Invoice ?? GetInvoice(state, action.InvoiceId)?.Data;
|
|
if (state._invoicesById.ContainsKey(action.InvoiceId))
|
|
state._invoicesById.Remove(action.InvoiceId);
|
|
return state with
|
|
{
|
|
_invoicesById = new Dictionary<string, RemoteData<InvoiceData>?>(state._invoicesById)
|
|
{
|
|
{ action.InvoiceId, new RemoteData<InvoiceData>(invoice, action.Error, false) }
|
|
}
|
|
};
|
|
}
|
|
}
|
|
|
|
protected class SetInvoicePaymentMethodsReducer : Reducer<StoreState, SetInvoicePaymentMethods>
|
|
{
|
|
public override StoreState Reduce(StoreState state, SetInvoicePaymentMethods action)
|
|
{
|
|
var pms = action.PaymentMethods ?? GetInvoicePaymentMethods(state, action.InvoiceId)?.Data;
|
|
if (state._invoicePaymentMethodsById.ContainsKey(action.InvoiceId))
|
|
state._invoicePaymentMethodsById.Remove(action.InvoiceId);
|
|
return state with
|
|
{
|
|
_invoicePaymentMethodsById = new Dictionary<string, RemoteData<InvoicePaymentMethodDataModel[]>?>(state._invoicePaymentMethodsById)
|
|
{
|
|
{ action.InvoiceId, new RemoteData<InvoicePaymentMethodDataModel[]>(pms, action.Error) }
|
|
}
|
|
};
|
|
}
|
|
}
|
|
|
|
protected class SetRatesReducer : Reducer<StoreState, SetRates>
|
|
{
|
|
public override StoreState Reduce(StoreState state, SetRates action)
|
|
{
|
|
return state with
|
|
{
|
|
Rates = (state.Rates ?? new RemoteData<IEnumerable<StoreRateResult>>()) with {
|
|
Data = action.Rates ?? state.Rates?.Data,
|
|
Error = action.Error,
|
|
Loading = false
|
|
}
|
|
};
|
|
}
|
|
}
|
|
|
|
protected class SetPointOfSaleReducer : Reducer<StoreState, SetPointOfSale>
|
|
{
|
|
public override StoreState Reduce(StoreState state, SetPointOfSale action)
|
|
{
|
|
return state with
|
|
{
|
|
PointOfSale = (state.PointOfSale ?? new RemoteData<PointOfSaleAppData>()) with
|
|
{
|
|
Data = action.AppData ?? state.PointOfSale?.Data,
|
|
Error = action.Error,
|
|
Loading = false,
|
|
Sending = false
|
|
}
|
|
};
|
|
}
|
|
}
|
|
|
|
protected class UpdatePointOfSaleReducer : Reducer<StoreState, UpdatePointOfSale>
|
|
{
|
|
public override StoreState Reduce(StoreState state, UpdatePointOfSale action)
|
|
{
|
|
return state with
|
|
{
|
|
PointOfSale = (state.PointOfSale ?? new RemoteData<PointOfSaleAppData>()) with
|
|
{
|
|
Sending = true
|
|
}
|
|
};
|
|
}
|
|
}
|
|
|
|
protected class SetPosItemStatsReducer : Reducer<StoreState, SetPosItemStats>
|
|
{
|
|
public override StoreState Reduce(StoreState state, SetPosItemStats action)
|
|
{
|
|
return state with
|
|
{
|
|
PosItemStats = (state.PosItemStats ?? new RemoteData<List<AppItemStats>>()) with
|
|
{
|
|
Data = action.ItemStats ?? state.PosItemStats?.Data,
|
|
Error = action.Error,
|
|
Loading = false,
|
|
Sending = false
|
|
}
|
|
};
|
|
}
|
|
}
|
|
|
|
protected class SetPosSalesStatsReducer : Reducer<StoreState, SetPosSalesStats>
|
|
{
|
|
public override StoreState Reduce(StoreState state, SetPosSalesStats action)
|
|
{
|
|
return state with
|
|
{
|
|
PosSalesStats = (state.PosSalesStats ?? new RemoteData<AppSalesStats>()) with
|
|
{
|
|
Data = action.SalesStats ?? state.PosSalesStats?.Data,
|
|
Error = action.Error,
|
|
Loading = false,
|
|
Sending = false
|
|
}
|
|
};
|
|
}
|
|
}
|
|
|
|
public RemoteData<InvoiceData>? GetInvoice(string invoiceId)
|
|
{
|
|
if (_invoicesById.TryGetValue(invoiceId, out var invoice)) return invoice;
|
|
var invoiceData = Invoices?.Data?.FirstOrDefault(i => i.Id == invoiceId);
|
|
return invoiceData == null ? null : new RemoteData<InvoiceData>(invoiceData);
|
|
}
|
|
|
|
private static RemoteData<InvoiceData>? GetInvoice(StoreState state, string invoiceId)
|
|
{
|
|
return state.GetInvoice(invoiceId);
|
|
}
|
|
|
|
public RemoteData<InvoicePaymentMethodDataModel[]>? GetInvoicePaymentMethods(string invoiceId)
|
|
{
|
|
return _invoicePaymentMethodsById.TryGetValue(invoiceId, out var pms) ? pms :null;
|
|
}
|
|
|
|
private static RemoteData<InvoicePaymentMethodDataModel[]>? GetInvoicePaymentMethods(StoreState state, string invoiceId)
|
|
{
|
|
return state.GetInvoicePaymentMethods(invoiceId);
|
|
}
|
|
|
|
private static HistogramData? GetUnifiedHistogram(HistogramData? onchain, HistogramData? lightning)
|
|
{
|
|
if (onchain == null && lightning == null) return null;
|
|
// if there's only one, return that
|
|
if (onchain == null || lightning == null) return onchain ?? lightning;
|
|
// if types or series differ, return null
|
|
if (onchain.Type != lightning.Type || onchain.Series?.Count != lightning.Series?.Count) return null;
|
|
// merge the two
|
|
var histogram = new HistogramData
|
|
{
|
|
Type = onchain.Type,
|
|
Series = onchain.Series,
|
|
Labels = onchain.Labels,
|
|
Balance = onchain.Balance + lightning.Balance,
|
|
};
|
|
for (var i = 0; i < lightning.Series!.Count; i++) histogram.Series![i] += lightning.Series[i];
|
|
return histogram;
|
|
}
|
|
|
|
public class StoreEffects(IState<StoreState> state, IState<UIState> uiState, IAccountManager accountManager)
|
|
{
|
|
[EffectMethod]
|
|
public Task SetStoreInfoEffect(SetStoreInfo action, IDispatcher dispatcher)
|
|
{
|
|
var store = action.StoreInfo;
|
|
if (store != null)
|
|
{
|
|
dispatcher.Dispatch(new RefreshStore(store));
|
|
|
|
var currency = BitcoinUnits.Contains(store.DefaultCurrency) ? null : store.DefaultCurrency;
|
|
dispatcher.Dispatch(new UIState.SetFiatCurrency(currency, true));
|
|
}
|
|
return Task.CompletedTask;
|
|
}
|
|
|
|
[EffectMethod]
|
|
public Task RefreshStoreEffect(RefreshStore action, IDispatcher dispatcher)
|
|
{
|
|
var store = action.Store;
|
|
var storeId = store.Id;
|
|
var posId = store.PosAppId!;
|
|
var histogramType = state.Value.HistogramType ?? uiState.Value.HistogramType;
|
|
dispatcher.Dispatch(new FetchStore(storeId));
|
|
dispatcher.Dispatch(new FetchBalances(storeId, histogramType));
|
|
dispatcher.Dispatch(new FetchNotifications(storeId));
|
|
dispatcher.Dispatch(new FetchInvoices(storeId));
|
|
dispatcher.Dispatch(new FetchRates(store));
|
|
dispatcher.Dispatch(new FetchPointOfSale(posId));
|
|
dispatcher.Dispatch(new FetchPointOfSaleStats(posId));
|
|
return Task.CompletedTask;
|
|
}
|
|
|
|
[EffectMethod]
|
|
public async Task FetchStoreEffect(FetchStore action, IDispatcher dispatcher)
|
|
{
|
|
try
|
|
{
|
|
var store = await accountManager.GetClient().GetStore(action.StoreId);
|
|
dispatcher.Dispatch(new SetStore(store, null));
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
var error = e.InnerException?.Message ?? e.Message;
|
|
dispatcher.Dispatch(new SetStore(null, error));
|
|
}
|
|
}
|
|
|
|
[EffectMethod]
|
|
public async Task UpdateStoreEffect(UpdateStore action, IDispatcher dispatcher)
|
|
{
|
|
try
|
|
{
|
|
var store = await accountManager.GetClient().UpdateStore(action.StoreId, action.Request);
|
|
dispatcher.Dispatch(new UpdatedStore(store, null));
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
var error = e.InnerException?.Message ?? e.Message;
|
|
dispatcher.Dispatch(new UpdatedStore(null, error));
|
|
}
|
|
}
|
|
|
|
[EffectMethod]
|
|
public Task FetchBalancesEffect(FetchBalances action, IDispatcher dispatcher)
|
|
{
|
|
dispatcher.Dispatch(new FetchOnchainBalance(action.StoreId));
|
|
dispatcher.Dispatch(new FetchLightningBalance(action.StoreId));
|
|
dispatcher.Dispatch(new FetchHistograms(action.StoreId, action.Type));
|
|
return Task.CompletedTask;
|
|
}
|
|
|
|
[EffectMethod]
|
|
public Task FetchHistogramsEffect(FetchHistograms action, IDispatcher dispatcher)
|
|
{
|
|
dispatcher.Dispatch(new FetchOnchainHistogram(action.StoreId, action.Type));
|
|
dispatcher.Dispatch(new FetchLightningHistogram(action.StoreId, action.Type));
|
|
return Task.CompletedTask;
|
|
}
|
|
|
|
[EffectMethod]
|
|
public async Task FetchOnchainBalanceEffect(FetchOnchainBalance action, IDispatcher dispatcher)
|
|
{
|
|
try
|
|
{
|
|
var overview = await accountManager.GetClient().ShowOnChainWalletOverview(action.StoreId, "BTC");
|
|
dispatcher.Dispatch(new SetOnchainBalance(overview, null));
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
var error = e.InnerException?.Message ?? e.Message;
|
|
dispatcher.Dispatch(new SetOnchainBalance(null, error));
|
|
}
|
|
}
|
|
|
|
[EffectMethod]
|
|
public async Task FetchLightningBalanceEffect(FetchLightningBalance action, IDispatcher dispatcher)
|
|
{
|
|
try
|
|
{
|
|
var balance = await accountManager.GetClient().GetLightningNodeBalance(action.StoreId, "BTC");
|
|
dispatcher.Dispatch(new SetLightningBalance(balance, null));
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
var error = e.InnerException?.Message ?? e.Message;
|
|
dispatcher.Dispatch(new SetLightningBalance(null, error));
|
|
}
|
|
}
|
|
|
|
[EffectMethod]
|
|
public async Task FetchOnchainHistogramEffect(FetchOnchainHistogram action, IDispatcher dispatcher)
|
|
{
|
|
try
|
|
{
|
|
var data = await accountManager.GetClient().GetOnChainWalletHistogram(action.StoreId, "BTC", action.Type);
|
|
dispatcher.Dispatch(new SetOnchainHistogram(data, null));
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
var error = e.InnerException?.Message ?? e.Message;
|
|
dispatcher.Dispatch(new SetOnchainHistogram(null, error));
|
|
}
|
|
}
|
|
|
|
[EffectMethod]
|
|
public async Task FetchLightningHistogramEffect(FetchLightningHistogram action, IDispatcher dispatcher)
|
|
{
|
|
try
|
|
{
|
|
var data = await accountManager.GetClient().GetLightningNodeHistogram(action.StoreId, "BTC", action.Type);
|
|
dispatcher.Dispatch(new SetLightningHistogram(data, null));
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
var error = e.InnerException?.Message ?? e.Message;
|
|
dispatcher.Dispatch(new SetLightningHistogram(null, error));
|
|
}
|
|
}
|
|
|
|
[EffectMethod]
|
|
public async Task FetchRolesEffect(FetchRoles action, IDispatcher dispatcher)
|
|
{
|
|
try
|
|
{
|
|
var roles = await accountManager.GetClient().GetStoreRoles(action.StoreId);
|
|
dispatcher.Dispatch(new SetRoles(roles, null));
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
var error = e.InnerException?.Message ?? e.Message;
|
|
dispatcher.Dispatch(new SetRoles(null, error));
|
|
}
|
|
}
|
|
|
|
[EffectMethod]
|
|
public async Task FetchUsersEffect(FetchUsers action, IDispatcher dispatcher)
|
|
{
|
|
try
|
|
{
|
|
var users = await accountManager.GetClient().GetStoreUsers(action.StoreId);
|
|
dispatcher.Dispatch(new SetUsers(users, null));
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
var error = e.InnerException?.Message ?? e.Message;
|
|
dispatcher.Dispatch(new SetUsers(null, error));
|
|
}
|
|
}
|
|
|
|
[EffectMethod]
|
|
public async Task FetchNotificationsEffect(FetchNotifications action, IDispatcher dispatcher)
|
|
{
|
|
try
|
|
{
|
|
var notifications = await accountManager.GetClient().GetNotifications(storeId: [action.StoreId]);
|
|
dispatcher.Dispatch(new SetNotifications(notifications, null));
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
var error = e.InnerException?.Message ?? e.Message;
|
|
dispatcher.Dispatch(new SetNotifications(null, error));
|
|
}
|
|
}
|
|
|
|
[EffectMethod]
|
|
public async Task UpdateNotificationEffect(UpdateNotification action, IDispatcher dispatcher)
|
|
{
|
|
try
|
|
{
|
|
var notification = await accountManager.GetClient().UpdateNotification(action.NotificationId, action.Seen);
|
|
dispatcher.Dispatch(new SetNotification(notification, null));
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
var error = e.InnerException?.Message ?? e.Message;
|
|
dispatcher.Dispatch(new SetNotification(null, error));
|
|
}
|
|
}
|
|
|
|
[EffectMethod]
|
|
public async Task UpdatePointOfSaleEffect(UpdatePointOfSale action, IDispatcher dispatcher)
|
|
{
|
|
try
|
|
{
|
|
var appData = await accountManager.GetClient().UpdatePointOfSaleApp(action.AppId, action.Request);
|
|
dispatcher.Dispatch(new UpdatedPointOfSale(appData, null));
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
var error = e.InnerException?.Message ?? e.Message;
|
|
dispatcher.Dispatch(new UpdatedPointOfSale(null, error));
|
|
}
|
|
}
|
|
|
|
[EffectMethod]
|
|
public async Task FetchPointOfSaleEffect(FetchPointOfSale action, IDispatcher dispatcher)
|
|
{
|
|
try
|
|
{
|
|
var appData = await accountManager.GetClient().GetPosApp(action.AppId);
|
|
dispatcher.Dispatch(new SetPointOfSale(appData, null));
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
var error = e.InnerException?.Message ?? e.Message;
|
|
dispatcher.Dispatch(new SetPointOfSale(null, error));
|
|
}
|
|
}
|
|
|
|
[EffectMethod]
|
|
public Task FetchPointOfSaleStatsEffect(FetchPointOfSaleStats action, IDispatcher dispatcher)
|
|
{
|
|
dispatcher.Dispatch(new FetchPosItemStats(action.AppId));
|
|
dispatcher.Dispatch(new FetchPosSalesStats(action.AppId));
|
|
return Task.CompletedTask;
|
|
}
|
|
|
|
[EffectMethod]
|
|
public async Task FetchPosItemStatsEffect(FetchPosItemStats action, IDispatcher dispatcher)
|
|
{
|
|
try
|
|
{
|
|
var data = await accountManager.GetClient().GetAppTopItems(action.AppId);
|
|
dispatcher.Dispatch(new SetPosItemStats(data, null));
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
var error = e.InnerException?.Message ?? e.Message;
|
|
dispatcher.Dispatch(new SetPosItemStats(null, error));
|
|
}
|
|
}
|
|
|
|
[EffectMethod]
|
|
public async Task FetchPosSalesStatsEffect(FetchPosSalesStats action, IDispatcher dispatcher)
|
|
{
|
|
try
|
|
{
|
|
var data = await accountManager.GetClient().GetAppSales(action.AppId);
|
|
dispatcher.Dispatch(new SetPosSalesStats(data, null));
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
var error = e.InnerException?.Message ?? e.Message;
|
|
dispatcher.Dispatch(new SetPosSalesStats(null, error));
|
|
}
|
|
}
|
|
|
|
[EffectMethod]
|
|
public async Task FetchRatesEffect(FetchRates action, IDispatcher dispatcher)
|
|
{
|
|
var currency = action.Store.DefaultCurrency;
|
|
if (BitcoinUnits.Contains(currency)) return;
|
|
try
|
|
{
|
|
var rates = await accountManager.GetClient().GetStoreRates(action.Store.Id, [$"BTC_{currency}"]);
|
|
dispatcher.Dispatch(new SetRates(rates, null));
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
var error = e.InnerException?.Message ?? e.Message;
|
|
dispatcher.Dispatch(new SetRates(null, error));
|
|
}
|
|
}
|
|
|
|
[EffectMethod]
|
|
public async Task FetchInvoicesEffect(FetchInvoices action, IDispatcher dispatcher)
|
|
{
|
|
try
|
|
{
|
|
var invoices = await accountManager.GetClient().GetInvoices(action.StoreId);
|
|
dispatcher.Dispatch(new SetInvoices(invoices, null));
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
var error = e.InnerException?.Message ?? e.Message;
|
|
dispatcher.Dispatch(new SetInvoices(null, error));
|
|
}
|
|
}
|
|
|
|
[EffectMethod]
|
|
public async Task FetchInvoiceEffect(FetchInvoice action, IDispatcher dispatcher)
|
|
{
|
|
try
|
|
{
|
|
var invoice = await accountManager.GetClient().GetInvoice(action.StoreId, action.InvoiceId);
|
|
dispatcher.Dispatch(new SetInvoice(invoice, null, action.InvoiceId));
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
var error = e.InnerException?.Message ?? e.Message;
|
|
dispatcher.Dispatch(new SetInvoice(null, error, action.InvoiceId));
|
|
}
|
|
}
|
|
|
|
[EffectMethod]
|
|
public async Task FetchInvoicePaymentMethodsEffect(FetchInvoicePaymentMethods action, IDispatcher dispatcher)
|
|
{
|
|
try
|
|
{
|
|
var pms = await accountManager.GetClient().GetInvoicePaymentMethods(action.StoreId, action.InvoiceId);
|
|
dispatcher.Dispatch(new SetInvoicePaymentMethods(pms, null, action.InvoiceId));
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
var error = e.InnerException?.Message ?? e.Message;
|
|
dispatcher.Dispatch(new SetInvoicePaymentMethods(null, error, action.InvoiceId));
|
|
}
|
|
}
|
|
|
|
[EffectMethod]
|
|
public Task SetHistogramTypeEffect(SetHistogramType action, IDispatcher dispatcher)
|
|
{
|
|
var storeInfo = state.Value.StoreInfo;
|
|
if (storeInfo != null)
|
|
dispatcher.Dispatch(new FetchHistograms(storeInfo.Id, action.Type));
|
|
return Task.CompletedTask;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|