diff --git a/NostrStreamer/ApiModel/BalanceHistoryItem.cs b/NostrStreamer/ApiModel/BalanceHistoryItem.cs new file mode 100644 index 0000000..a726b57 --- /dev/null +++ b/NostrStreamer/ApiModel/BalanceHistoryItem.cs @@ -0,0 +1,24 @@ +using Newtonsoft.Json; + +namespace NostrStreamer.ApiModel; + +public enum BalanceHistoryItemType +{ + Credit, + Debit +} + +public class BalanceHistoryItem +{ + [JsonProperty("created")] + public DateTime Created { get; init; } + + [JsonProperty("type")] + public BalanceHistoryItemType Type { get; init; } + + [JsonProperty("amount")] + public decimal Amount { get; init; } + + [JsonProperty("desc")] + public string? Description { get; init; } +} \ No newline at end of file diff --git a/NostrStreamer/Controllers/NostrController.cs b/NostrStreamer/Controllers/NostrController.cs index bf0714b..075c4be 100644 --- a/NostrStreamer/Controllers/NostrController.cs +++ b/NostrStreamer/Controllers/NostrController.cs @@ -362,11 +362,46 @@ public class NostrController : Controller if (string.IsNullOrEmpty(userPubkey)) return BadRequest(); - var (fee, preimage) = await _userService.WithdrawFunds(userPubkey, invoice); - return Json(new + try { - fee, preimage - }); + var (fee, preimage) = await _userService.WithdrawFunds(userPubkey, invoice); + return Json(new + { + fee, preimage + }); + } + catch (Exception e) + { + return Json(new + { + error = e.Message + }); + } + } + + [HttpGet("history")] + public async Task BalanceHistory([FromQuery] int page = 0, [FromQuery] int pageSize = 100) + { + var userPubkey = GetPubKey(); + if (string.IsNullOrEmpty(userPubkey)) + return BadRequest(); + + try + { + var txns = await _userService.BalanceHistory(userPubkey, page * pageSize, pageSize); + return Json(new + { + items = txns, + page, pageSize + }); + } + catch (Exception e) + { + return Json(new + { + error = e.Message + }); + } } private async Task GetUser() diff --git a/NostrStreamer/Services/UserService.cs b/NostrStreamer/Services/UserService.cs index 52146b2..5b42bbb 100644 --- a/NostrStreamer/Services/UserService.cs +++ b/NostrStreamer/Services/UserService.cs @@ -149,13 +149,44 @@ public class UserService } } - public async Task> ListPayments(string pubkey) + public async Task> ListPayments(string pubkey, int offset = 0, int limit = 100) { return await _db.Payments .Where(a => a.PubKey == pubkey && a.IsPaid) + .Skip(offset) + .Take(limit) .ToListAsync(); } + public async Task> BalanceHistory(string pubkey, int offset = 0, int limit = 100) + { + return await _db.Payments + .Where(a => a.PubKey == pubkey && a.IsPaid) + .Select(t => new BalanceHistoryItem + { + Created = t.Created, + Type = t.Type == PaymentType.Withdrawal ? BalanceHistoryItemType.Debit : BalanceHistoryItemType.Credit, + Description = t.Type == PaymentType.Withdrawal + ? "Withdrawal" + : (t.Type == PaymentType.Credit ? "Admin Credit" : ""), + Amount = t.Amount / 1000m + }) + .Union(_db.Streams + .Where(a => a.PubKey == pubkey && a.State == UserStreamState.Ended) + .Select(t => new BalanceHistoryItem + { + Created = t.Starts, + Description = t.Event, + Type = BalanceHistoryItemType.Debit, + Amount = t.MilliSatsCollected / 1000m + })) + .OrderByDescending(a => a.Created) + .Skip(offset) + .Take(limit) + .ToListAsync(); + } + + public async Task MaxWithdrawalAmount(string pubkey) { var credit = await _db.Payments