using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using BTCPayServer.Data; using Microsoft.EntityFrameworkCore; namespace BTCPayServer.Services { public class WalletRepository { private readonly ApplicationDbContextFactory _ContextFactory; public WalletRepository(ApplicationDbContextFactory contextFactory) { _ContextFactory = contextFactory ?? throw new ArgumentNullException(nameof(contextFactory)); } public async Task SetWalletInfo(WalletId walletId, WalletBlobInfo blob) { ArgumentNullException.ThrowIfNull(walletId); using var ctx = _ContextFactory.CreateContext(); var walletData = new WalletData() { Id = walletId.ToString() }; walletData.SetBlobInfo(blob); var entity = await ctx.Wallets.AddAsync(walletData); entity.State = EntityState.Modified; try { await ctx.SaveChangesAsync(); } catch (DbUpdateException) // Does not exists { entity.State = EntityState.Added; await ctx.SaveChangesAsync(); } } public async Task> GetWalletTransactionsInfo(WalletId walletId, string[] transactionIds = null) { ArgumentNullException.ThrowIfNull(walletId); using var ctx = _ContextFactory.CreateContext(); return (await ctx.WalletTransactions .Where(w => w.WalletDataId == walletId.ToString()) .Where(data => transactionIds == null || transactionIds.Contains(data.TransactionId)) .Select(w => w) .ToArrayAsync()) .ToDictionary(w => w.TransactionId, w => w.GetBlobInfo()); } public async Task GetWalletInfo(WalletId walletId) { ArgumentNullException.ThrowIfNull(walletId); using var ctx = _ContextFactory.CreateContext(); var data = await ctx.Wallets .Where(w => w.Id == walletId.ToString()) .Select(w => w) .FirstOrDefaultAsync(); return data?.GetBlobInfo() ?? new WalletBlobInfo(); } public async Task SetWalletTransactionInfo(WalletId walletId, string transactionId, WalletTransactionInfo walletTransactionInfo) { ArgumentNullException.ThrowIfNull(walletId); ArgumentNullException.ThrowIfNull(transactionId); using var ctx = _ContextFactory.CreateContext(); var walletData = new WalletTransactionData() { WalletDataId = walletId.ToString(), TransactionId = transactionId }; walletData.SetBlobInfo(walletTransactionInfo); var entity = await ctx.WalletTransactions.AddAsync(walletData); entity.State = EntityState.Modified; try { await ctx.SaveChangesAsync(); } catch (DbUpdateException) // Does not exists { entity.State = EntityState.Added; try { await ctx.SaveChangesAsync(); } catch (DbUpdateException) // the Wallet does not exists in the DB { await SetWalletInfo(walletId, new WalletBlobInfo()); await ctx.SaveChangesAsync(); } } } } }