← Code knowledge base
Reviewed Flutter implementation · 2026-10-27

MobileCardAutoTopUpController.cs

backend/src/NeoBanking.Api/Controllers/MobileCardAutoTopUpController.cs

Immutable source snapshot based on revision de78e63ed65c. Original line numbers are retained. This is implementation evidence; check the public API catalogue before adapting it.

The mobile /api/v1/mobile routes belong to the example backend. Company credentials stay on that backend. Some sections outside the documented product scope may be omitted.

Lines 1–61

using System.Net.Http;using System.Text.Json;using Microsoft.AspNetCore.Authorization;using Microsoft.AspNetCore.Mvc;using NeoBanking.Application.Common;using NeoBanking.Application.Security;using NeoBanking.Application.UseCases.Hoppa; namespace NeoBanking.Api.Controllers; [Authorize(Policy = AuthorizationPolicyNames.User)][Route("api/v1/mobile/cards")]public sealed class MobileCardAutoTopUpController(IProxyHoppaRequestUseCase proxy) : ApiControllerBase{    [HttpGet("{cardId:int}/auto-topup")]    public Task<ActionResult<JsonElement?>> Get(int cardId, CancellationToken ct) =>        Send(HttpMethod.Get, $"cards/{cardId}/auto-topup", cardId, (object?)null, ct);     [HttpPost("auto-topup/low-balance")]    public Task<ActionResult<JsonElement?>> LowBalance(LowBalanceRequest request, CancellationToken ct) =>        Send(HttpMethod.Post, "cards/auto-topup/low-balance", request.CardId, request, ct,            !request.Enabled || (request.DisclaimerAccepted && request.Watermark > 0 &&                request.TargetBalance > request.Watermark && request.MonthlyLimit > 0));     [HttpPost("auto-topup/failed-tx")]    public Task<ActionResult<JsonElement?>> FailedTransaction(FailedTransactionRequest request, CancellationToken ct) =>        Send(HttpMethod.Post, "cards/auto-topup/failed-tx", request.CardId, request, ct,            !request.Enabled || (request.DisclaimerAccepted && request.MaxAmount > 0 && request.MonthlyLimit > 0));     [HttpPost("auto-topup/deposit")]    public Task<ActionResult<JsonElement?>> Deposit(DepositRequest request, CancellationToken ct)    {        var settings = request.Settings;        var valid = settings is { Count: > 0 and <= 2 } && settings.All(s => s is not null &&            (s.Currency == "USDC" || s.Currency == "USDT") &&            (!s.Enabled || (s.MaxAmount > 0 && request.DisclaimerAccepted))) &&            settings.Select(s => s.Currency).Distinct().Count() == settings.Count;        return Send(HttpMethod.Post, "cards/auto-topup/deposit", request.CardId, request, ct, valid);    }     private async Task<ActionResult<JsonElement?>> Send<T>(HttpMethod method, string path, int cardId, T body,        CancellationToken ct, bool valid = true)    {        if (!TryGetCurrentUserId(out var userId) || !int.TryParse(userId, out var numericUser) || numericUser <= 0)            return MissingIdentity<JsonElement?>();        if (cardId <= 0 || !valid)            return ToActionResult(ApplicationResult<JsonElement?>.Failure(new ApplicationError(                "mobile.cards.auto_topup.invalid", "Check the amounts and accept the automatic top-up authorization before enabling.", 400)));        // No caller-supplied userId is accepted. Hoppa also verifies company/card ownership.        return ToActionResult(await proxy.ExecuteAsync(new ProxyHoppaRequestCommand<T> {            Method = method, UpstreamPath = $"/api/v2/{path}", Request = body,            Query = new Dictionary<string, string?> { ["userId"] = userId },            FailureCode = "mobile.cards.auto_topup.failed", FailureMessage = "Unable to update automatic top-up settings."        }, ct));    }     public sealed record LowBalanceRequest(int CardId, bool Enabled, decimal Watermark, decimal TargetBalance, decimal MonthlyLimit, bool DisclaimerAccepted);    public sealed record FailedTransactionRequest(int CardId, bool Enabled, decimal MaxAmount, decimal MonthlyLimit, bool DisclaimerAccepted);    public sealed record DepositRequest(int CardId, bool DisclaimerAccepted, List<DepositSetting>? Settings);    public sealed record DepositSetting(string Currency, bool Enabled, decimal MaxAmount);}
HOPPA DEVELOPER ASSISTANT

What are you building?

From a question to an implementation.

Get a step-by-step flow, example code and the docs behind it. Choose a starting point or describe your feature.

Answers use the public API guide and example app code. Check the linked reference before shipping. Explore code sources ↗

Your question and recent conversation are sent to our AI provider. Don’t include API keys, personal data or card details.