mirror of
https://github.com/btcpayserver/btcpayserver.git
synced 2025-03-06 10:32:13 +01:00
* WIP New APIs for dealing with custodians/exchanges * Simplified things * More API refinements + index.html file for quick viewing * Finishing touches on spec * Switched cryptoCode to paymentMethod as this allows us to differentiate between onchain and lightning * Moved draft API docs to "/docs-draft" * WIP baby steps * Added DB migration for CustodianAccountData * Rough but working POST /v1/api/custodian-account + GET /v1/api/custodian * WIP + early Kraken API client * Moved service registration to proper location * Working create + list custodian accounts + permissions + WIP Kraken client * Kraken API Balances call is working * Added asset balances to response * List Custodian Accounts call does not load assetBalances by default, because it can fail. Can be requested when needed. * Call to get the details of 1 specific custodian account * Added permissions to swagger * Added "tradableAssetPairs" to Kraken custodian response + cache the tradable pairs in memory for 24 hours * Removed unused file * WIP + Moved files to better locations * Updated docs * Working API endpoint to get info on a trade (same response as creating a new trade) * Working API endpoints for Deposit + Trade + untested Withdraw * Delete custodian account * Trading works, better error handling, cleanup * Working withdrawals + New endpoint for getting bid/ask prices * Completed withdrawals + new endpoint for getting info on a past withdrawal to simplify testing, Enums are output as strings, * Better error handling when withdrawing to a wrong destination * WithdrawalAddressName in config is now a string per currency (dictionary) * Added TODOs * Only show the custodian account "config" to users who are allowed * Added the new permissions to the API Keys UI * Renamed KrakenClient to KrakenExchange * WIP Kraken Config Form * Removed files for UI again, will make separate PR later * Fixed docs + Refactored to use PaymentMethod more + Added "name" to custodian account + Using cancelationToken everywhere * Updated withdrawal info docs * First unit test * Complete tests for /api/v1/custodians and /api/v1/custodian-accounts endpoints + Various improvements and fixes * Mock custodian and more exceptions * Many more tests + cleanup, moved files to better locations * More tests * WIP more tests * Greenfield API tests complete * Added missing "Name" column * Cleanup, TODOs and beginning of Kraken Tests * Added Kraken tests using public endpoints + handling of "SATS" currency * Added 1st mocked Kraken API call: GetAssetBalancesAsync * Added assert for bad config * Mocked more Kraken API responses + added CreationDate to withdrawal response * pr review club changes * Make Kraken Custodian a plugin * Re-added User-Agent header as it is required * Fixed bug in market trade on Kraken using a percentage as qty * A short delay so Kraken has the time to execute the market order and we don't fetch the details too quickly. * Merged the draft swagger into the main swagger since it didn't work anymore * Fixed API permissions test * Removed 2 TODOs * Fixed unit test * After a utxo rescan, the cached balance should be invalidated * Fixed Kraken plugin build issues * Added Kraken plugin to build * WIP UI + config form * Create custodian account almost working - only need to add in the config form * Working form, but lacks refinement * Viewing balances + Editing custodian account works, but cannot change the withdrawal destination config because that is an object using a name with [] in it * cleanup * Minor cleanup, comments * Working: Delete custodian account * Moved the MockCustodian used in tests to a new plugin + linked it to the tests * WIP viewing custodian account balances * Split the Mock custodian into a Mock + Fake, various UI improvements and minor fixes * Minor UI fixes * Removed broken link * Removed links to anchors as they cannot pass the tests since they use JavaScript * Removed non-existing link. Even though it was commented out, the test still broke? * Added TODOs * Now throwing BadConfigException if API key is invalid * UI improvements * Commented out unfinished API endpoints. Can be finished later. * Show fiat value for fiat assets * Removed Kraken plugin so I can make a PR Removed more Kraken files * Add experimental route on UICustodianAccountsControllre * Removed unneeded code * Cleanup code * Processed Nicolas' feedback Co-authored-by: Kukks <evilkukka@gmail.com> Co-authored-by: nicolas.dorier <nicolas.dorier@gmail.com>
190 lines
8 KiB
Text
190 lines
8 KiB
Text
@using BTCPayServer.Views.Apps
|
|
@using Microsoft.AspNetCore.Mvc.TagHelpers
|
|
@using BTCPayServer.Abstractions.Extensions
|
|
@using BTCPayServer.Abstractions.Custodians
|
|
@model BTCPayServer.Models.CustodianAccountViewModels.ViewCustodianAccountViewModel
|
|
@{
|
|
ViewData.SetActivePage(AppsNavPages.Create, "Custodian account: " + @Model?.CustodianAccount.Name);
|
|
}
|
|
|
|
@section PageFootContent {
|
|
<partial name="_ValidationScriptsPartial"/>
|
|
}
|
|
|
|
|
|
<partial name="_StatusMessage"/>
|
|
|
|
<div class="sticky-header-setup"></div>
|
|
<div class="sticky-header d-sm-flex align-items-center justify-content-between">
|
|
<h2 class="mb-0">
|
|
@ViewData["Title"]
|
|
</h2>
|
|
<div class="d-flex gap-3 mt-3 mt-sm-0">
|
|
<a asp-action="EditCustodianAccount" asp-route-storeId="@Model.CustodianAccount.StoreId" asp-route-accountId="@Model.CustodianAccount.Id" class="btn btn-primary mt-3 mt-sm-0" role="button" id="EditCustodianAccountConfig">
|
|
<span class="fa fa-gear"></span> Configure
|
|
</a>
|
|
<a asp-action="DeleteCustodianAccount" asp-route-storeId="@Model.CustodianAccount.StoreId" asp-route-accountId="@Model.CustodianAccount.Id" class="btn btn-danger mt-3 mt-sm-0" role="button" id="DeleteCustodianAccountConfig">
|
|
<span class="fa fa-trash"></span> Delete
|
|
</a>
|
|
<!--
|
|
<button type="submit" class="btn btn-primary order-sm-1" id="SaveSettings">Save</button>
|
|
<a class="btn btn-secondary" id="ViewApp" target="app_" href="/apps/MQ2sCVsmQ95JBZ4aZDtoSwMAnBY/pos">View</a>
|
|
-->
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<div class="row">
|
|
<div class="col-xl-12">
|
|
|
|
@if (@Model.GetAssetBalanceException != null)
|
|
{
|
|
<p class="alert alert-danger">
|
|
@Model.GetAssetBalanceException.Message
|
|
</p>
|
|
}
|
|
|
|
<h2>Balances</h2>
|
|
<div class="table-responsive">
|
|
<table class="table table-hover table-responsive-md">
|
|
<thead>
|
|
<tr>
|
|
<th>Asset</th>
|
|
<th class="text-end">Balance</th>
|
|
<th class="text-end">Unit Price (Bid)</th>
|
|
<th class="text-end">Unit Price (Ask)</th>
|
|
<th class="text-end">Fiat Value</th>
|
|
<th class="text-end">Actions</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
@if (Model.AssetBalances != null && Model.AssetBalances.Count > 0)
|
|
{
|
|
@foreach (var pair in Model.AssetBalances.OrderBy(key => key.Key))
|
|
{
|
|
<tr>
|
|
<td>@pair.Key</td>
|
|
<!-- TODO format as number? How? -->
|
|
<th class="text-end">@pair.Value.Qty</th>
|
|
<th class="text-end">
|
|
@pair.Value.FormattedBid
|
|
</th>
|
|
<th class="text-end">
|
|
@pair.Value.FormattedAsk
|
|
</th>
|
|
<th class="text-end">
|
|
@(pair.Value.FormattedFiatValue)
|
|
</th>
|
|
<th class="text-end">
|
|
@if (pair.Value.TradableAssetPairs != null)
|
|
{
|
|
<a data-bs-toggle="modal" data-bs-target="#tradeModal" href="#">Trade</a>
|
|
}
|
|
@if (pair.Value.CanDeposit)
|
|
{
|
|
<a data-bs-toggle="modal" data-bs-target="#depositModal" href="#">Deposit</a>
|
|
}
|
|
@if (pair.Value.CanWithdraw)
|
|
{
|
|
<a data-bs-toggle="modal" data-bs-target="#withdrawModal" href="#">Withdraw</a>
|
|
}
|
|
</th>
|
|
</tr>
|
|
}
|
|
}
|
|
else if (Model.GetAssetBalanceException == null)
|
|
{
|
|
<tr>
|
|
<td colspan="999" class="text-center">No assets are stored with this custodian (yet).</td>
|
|
</tr>
|
|
}
|
|
else
|
|
{
|
|
<tr>
|
|
<td colspan="999" class="text-center">An error occured while loading assets and balances.</td>
|
|
</tr>
|
|
}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
|
|
|
|
<h2>Features</h2>
|
|
<p>The @Model.Custodian.Name custodian supports:</p>
|
|
<ul>
|
|
<li>Viewing asset balances</li>
|
|
@if (Model.Custodian is ICanTrade)
|
|
{
|
|
<li>Trading (Greenfield API only, for now)</li>
|
|
}
|
|
@if (Model.Custodian is ICanDeposit)
|
|
{
|
|
<li>Depositing (Greenfield API only, for now)</li>
|
|
}
|
|
@if (Model.Custodian is ICanWithdraw)
|
|
{
|
|
<li>Withdrawing (Greenfield API only, for now)</li>
|
|
}
|
|
</ul>
|
|
|
|
|
|
</div>
|
|
</div>
|
|
|
|
|
|
<div class="modal" tabindex="-1" role="dialog" id="withdrawModal">
|
|
<div class="modal-dialog" role="document">
|
|
<div class="modal-content">
|
|
<div class="modal-header">
|
|
<h5 class="modal-title">Withdraw</h5>
|
|
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close">
|
|
<vc:icon symbol="close"/>
|
|
</button>
|
|
</div>
|
|
<div class="modal-body">
|
|
<p>Withdrawals are coming soon, but if you need this today, you can use our <a rel="noopener noreferrer" href="https://docs.btcpayserver.org/API/Greenfield/v1/" target="_blank">Greenfield API "Withdraw to store wallet" endpoint</a> to execute a withdrawal.</p>
|
|
</div>
|
|
<div class="modal-footer">
|
|
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="modal" tabindex="-1" role="dialog" id="depositModal">
|
|
<div class="modal-dialog" role="document">
|
|
<div class="modal-content">
|
|
<div class="modal-header">
|
|
<h5 class="modal-title">Deposit</h5>
|
|
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close">
|
|
<vc:icon symbol="close"/>
|
|
</button>
|
|
</div>
|
|
<div class="modal-body">
|
|
<p>Deposits are coming soon, but if you need this today, you can use our <a rel="noopener noreferrer" href="https://docs.btcpayserver.org/API/Greenfield/v1/" target="_blank">Greenfield API "Get a deposit address for custodian" endpoint</a> to get a deposit address to send your assets to.</p>
|
|
</div>
|
|
<div class="modal-footer">
|
|
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="modal" tabindex="-1" role="dialog" id="tradeModal">
|
|
<div class="modal-dialog" role="document">
|
|
<div class="modal-content">
|
|
<div class="modal-header">
|
|
<h5 class="modal-title">Trade</h5>
|
|
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close">
|
|
<vc:icon symbol="close"/>
|
|
</button>
|
|
</div>
|
|
<div class="modal-body">
|
|
<p>Trades are coming soon, but if you need this today, you can use our <a rel="noopener noreferrer" href="https://docs.btcpayserver.org/API/Greenfield/v1/" target="_blank"> Greenfield API "Trade one asset for another" endpoint</a> to convert an asset to another via a market order.</p>
|
|
</div>
|
|
<div class="modal-footer">
|
|
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|