Skip to content
Closed
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 60 additions & 1 deletion OpenApi.yml
Original file line number Diff line number Diff line change
Expand Up @@ -520,7 +520,6 @@ components:
ProviderDetail:
properties:
fee:
deprecated: true
Comment thread
Dominikkq marked this conversation as resolved.
Outdated
type: integer
feePercentage:
type: number
Expand Down Expand Up @@ -684,6 +683,38 @@ components:
rsk:
type: string
type: object
SummaryData:
properties:
acceptedQuotesCount:
type: integer
lpEarnings:
$ref: '#/components/schemas/Wei'
paidQuotesAmount:
$ref: '#/components/schemas/Wei'
paidQuotesCount:
type: integer
refundedQuotesCount:
type: integer
totalAcceptedQuotedAmount:
$ref: '#/components/schemas/Wei'
totalFeesCollected:
$ref: '#/components/schemas/Wei'
totalPenaltyAmount:
$ref: '#/components/schemas/Wei'
totalQuotesCount:
type: integer
type: object
SummaryResult:
properties:
peginSummary:
$ref: '#/components/schemas/SummaryData'
type: object
pegoutSummary:
$ref: '#/components/schemas/SummaryData'
type: object
type: object
Wei: {}
entities.Wei: {}
pkg.AcceptQuoteRequest:
properties:
quoteHash:
Expand Down Expand Up @@ -1034,6 +1065,34 @@ paths:
"204":
description: ""
summary: Withdraw PegIn Collateral
/report/summaries:
get:
description: ' Returns financial data for a given period'
parameters:
- description: Start date in YYYY-MM-DD format
in: query
name: startDate
required: true
schema:
description: Start date in YYYY-MM-DD format
format: string
type: string
- description: End date in YYYY-MM-DD format
in: query
name: endDate
required: true
schema:
description: End date in YYYY-MM-DD format
format: string
type: string
responses:
"200":
content:
application/json:
schema:
$ref: '#/components/schemas/SummaryResult'
description: Financial data for the given period
summary: Summaries
/userQuotes:
get:
description: ' Returns user quotes for address.'
Expand Down
59 changes: 59 additions & 0 deletions internal/adapters/dataproviders/database/mongo/pegin.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import (
"context"
"errors"
"fmt"
"time"

"github.com/rsksmart/liquidity-provider-server/internal/entities/quote"
"github.com/rsksmart/liquidity-provider-server/internal/usecases"
log "github.com/sirupsen/logrus"
Expand Down Expand Up @@ -208,3 +210,60 @@ func (repo *peginMongoRepository) DeleteQuotes(ctx context.Context, quotes []str
}
return uint(peginResult.DeletedCount + retainedResult.DeletedCount + creationDataResult.DeletedCount), nil
}

func (repo *peginMongoRepository) ListQuotesByDateRange(ctx context.Context, startDate, endDate time.Time) ([]quote.PeginQuote, []quote.RetainedPeginQuote, error) {
Comment thread
Dominikkq marked this conversation as resolved.
Outdated
quotes := make([]quote.PeginQuote, 0)
retainedQuotes := make([]quote.RetainedPeginQuote, 0)
dbCtx, cancel := context.WithTimeout(ctx, repo.conn.timeout)
defer cancel()
startTimestamp := int64(startDate.Unix())
endTimestamp := int64(endDate.Unix())
quoteCollection := repo.conn.Collection(PeginQuoteCollection)
quoteFilter := bson.D{
primitive.E{
Key: "agreement_timestamp",
Value: bson.D{
primitive.E{Key: "$gte", Value: startTimestamp},
primitive.E{Key: "$lte", Value: endTimestamp},
},
},
}
quoteCursor, err := quoteCollection.Find(dbCtx, quoteFilter)
if err != nil {
return quotes, retainedQuotes, err
}
defer quoteCursor.Close(dbCtx)
Comment thread
Dominikkq marked this conversation as resolved.
Outdated
var storedQuotes []StoredPeginQuote
if err = quoteCursor.All(dbCtx, &storedQuotes); err != nil {
return quotes, retainedQuotes, err
}
quoteHashes := make([]string, 0, len(storedQuotes))
for _, stored := range storedQuotes {
quotes = append(quotes, stored.PeginQuote)
quoteHashes = append(quoteHashes, stored.Hash)
}
if len(quoteHashes) > 0 {
retainedCollection := repo.conn.Collection(RetainedPeginQuoteCollection)
retainedFilter := bson.D{
primitive.E{
Key: "quote_hash",
Value: bson.D{
primitive.E{Key: "$in", Value: quoteHashes},
},
},
}
retainedCursor, err := retainedCollection.Find(dbCtx, retainedFilter)
if err != nil {
return quotes, retainedQuotes, err
}
defer retainedCursor.Close(dbCtx)
if err = retainedCursor.All(dbCtx, &retainedQuotes); err != nil {
return quotes, retainedQuotes, err
}
}
logDbInteraction(Read, map[string]interface{}{
"quotes": quotes,
"retainedQuotes": retainedQuotes,
})
return quotes, retainedQuotes, nil
}
62 changes: 61 additions & 1 deletion internal/adapters/dataproviders/database/mongo/pegout.go
Comment thread
Dominikkq marked this conversation as resolved.
Comment thread
Dominikkq marked this conversation as resolved.
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,16 @@ import (
"context"
"errors"
"fmt"
"regexp"
"time"

"github.com/rsksmart/liquidity-provider-server/internal/entities/quote"
"github.com/rsksmart/liquidity-provider-server/internal/usecases"
log "github.com/sirupsen/logrus"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/bson/primitive"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
"regexp"
)

const (
Expand Down Expand Up @@ -319,3 +321,61 @@ func (repo *pegoutMongoRepository) UpsertPegoutDeposits(ctx context.Context, dep
}
return err
}

func (repo *pegoutMongoRepository) ListQuotesByDateRange(ctx context.Context, startDate, endDate time.Time) ([]quote.PegoutQuote, []quote.RetainedPegoutQuote, error) {
quotes := make([]quote.PegoutQuote, 0)
retainedQuotes := make([]quote.RetainedPegoutQuote, 0)

dbCtx, cancel := context.WithTimeout(ctx, repo.conn.timeout)
defer cancel()
startTimestamp := int64(startDate.Unix())
endTimestamp := int64(endDate.Unix())
quoteCollection := repo.conn.Collection(PegoutQuoteCollection)
quoteFilter := bson.D{
primitive.E{
Key: "agreement_timestamp",
Value: bson.D{
primitive.E{Key: "$gte", Value: startTimestamp},
primitive.E{Key: "$lte", Value: endTimestamp},
},
},
}
quoteCursor, err := quoteCollection.Find(dbCtx, quoteFilter)
if err != nil {
return quotes, retainedQuotes, err
}
defer quoteCursor.Close(dbCtx)
var storedQuotes []StoredPegoutQuote
if err = quoteCursor.All(dbCtx, &storedQuotes); err != nil {
return quotes, retainedQuotes, err
}
quoteHashes := make([]string, 0, len(storedQuotes))
for _, stored := range storedQuotes {
quotes = append(quotes, stored.PegoutQuote)
quoteHashes = append(quoteHashes, stored.Hash)
}
if len(quoteHashes) > 0 {
retainedCollection := repo.conn.Collection(RetainedPegoutQuoteCollection)
retainedFilter := bson.D{
primitive.E{
Key: "quote_hash",
Value: bson.D{
primitive.E{Key: "$in", Value: quoteHashes},
},
},
}
retainedCursor, err := retainedCollection.Find(dbCtx, retainedFilter)
if err != nil {
return quotes, retainedQuotes, err
}
defer retainedCursor.Close(dbCtx)
if err = retainedCursor.All(dbCtx, &retainedQuotes); err != nil {
return quotes, retainedQuotes, err
}
}
logDbInteraction(Read, map[string]interface{}{
"quotes": quotes,
"retainedQuotes": retainedQuotes,
})
return quotes, retainedQuotes, nil
}
45 changes: 45 additions & 0 deletions internal/adapters/entrypoints/rest/assets/management.html
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,51 @@ <h5 class="card-title">Current Configuration</h5>
</div>
</div>
</div>
<div class="row mt-3">
<div class="col-md-12">
<div class="card">
<div class="card-header">Reports</div>
<div class="card-body">
<h5 class="card-title">Financial Summaries</h5>
<div class="row">
<div class="col-md-5">
<div class="mb-3">
<label for="summaryStartDate" class="form-label">Start Date</label>
<input type="date" class="form-control" id="summaryStartDate">
</div>
</div>
<div class="col-md-5">
<div class="mb-3">
<label for="summaryEndDate" class="form-label">End Date</label>
<input type="date" class="form-control" id="summaryEndDate">
</div>
</div>
<div class="col-md-2 d-flex align-items-end">
<div class="mb-3">
<button type="button" class="btn btn-primary" id="fetchSummariesButton">Generate Report</button>
</div>
</div>
</div>
<div id="summariesResult" style="display: none;">
<div class="row mt-3">
<div class="col-md-6">
<div class="card">
<div class="card-header">Pegin Summary</div>
<div class="card-body" id="peginSummary"></div>
</div>
</div>
<div class="col-md-6">
<div class="card">
<div class="card-header">Pegout Summary</div>
<div class="card-body" id="pegoutSummary"></div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>

<div class="toast-container">
Expand Down
14 changes: 14 additions & 0 deletions internal/adapters/entrypoints/rest/assets/static/management.css
Original file line number Diff line number Diff line change
Expand Up @@ -46,3 +46,17 @@ pre {
50% { width: 50%; }
100% { width: 100%; }
}

#summariesResult {
margin-top: 20px;
}

#peginSummary table,
#pegoutSummary table {
margin-bottom: 0;
}

#peginSummary th,
#pegoutSummary th {
width: 60%;
}
64 changes: 64 additions & 0 deletions internal/adapters/entrypoints/rest/assets/static/management.js
Original file line number Diff line number Diff line change
Expand Up @@ -572,6 +572,62 @@ const addCollateral = async (amountId, endpoint, elementId, loadingBarId, button
}
};

const displaySummaryData = (container, data) => {
container.innerHTML = '';
const table = document.createElement('table');
table.classList.add('table', 'table-striped');
const rows = [
{ label: 'Total Quotes', value: data.totalQuotesCount },
{ label: 'Accepted Quotes', value: data.acceptedQuotesCount },
{ label: 'Paid Quotes', value: data.paidQuotesCount },
{ label: 'Paid Quotes Amount', value: data.paidQuotesAmount },
{ label: 'Total Accepted Amount', value: data.totalAcceptedQuotedAmount },
{ label: 'Total Fees Collected', value: data.totalFeesCollected },
{ label: 'Refunded Quotes', value: data.refundedQuotesCount },
{ label: 'Total Penalty Amount', value: data.totalPenaltyAmount },
{ label: 'LP Earnings', value: data.lpEarnings }
];
rows.forEach(row => {
const tr = document.createElement('tr');
const th = document.createElement('th');
th.textContent = row.label;
const td = document.createElement('td');
td.textContent = row.value;
tr.appendChild(th);
tr.appendChild(td);
table.appendChild(tr);
});
container.appendChild(table);
};

const fetchSummariesReport = async (csrfToken) => {
const startDate = document.getElementById('summaryStartDate').value;
const endDate = document.getElementById('summaryEndDate').value;
if (!startDate || !endDate) {
showErrorToast('Please select both start and end dates');
return;
}
try {
const response = await fetch(`/report/summaries?startDate=${startDate}&endDate=${endDate}`, {
method: 'GET',
headers: {
'Content-Type': 'application/json',
'X-CSRF-Token': csrfToken
}
});
if (!response.ok) {
const errorData = await response.json();
throw new Error(errorData.message || 'Failed to fetch summaries');
}
const data = await response.json();
document.getElementById('summariesResult').style.display = 'block';
displaySummaryData(document.getElementById('peginSummary'), data.peginSummary);
displaySummaryData(document.getElementById('pegoutSummary'), data.pegoutSummary);
} catch (error) {
showErrorToast(`Error fetching summaries: ${error.message}`);
}
};

document.addEventListener('DOMContentLoaded', () => {
const csrfToken = data.CsrfToken;
const configurations = data.Configuration;
Expand All @@ -582,6 +638,7 @@ document.addEventListener('DOMContentLoaded', () => {
document.getElementById('addPeginCollateralButton').addEventListener('click', () => addCollateral('addPeginCollateralAmount', '/pegin/addCollateral', 'peginCollateral', 'peginLoadingBar', 'addPeginCollateralButton', csrfToken));
document.getElementById('addPegoutCollateralButton').addEventListener('click', () => addCollateral('addPegoutCollateralAmount', '/pegout/addCollateral', 'pegoutCollateral', 'pegoutLoadingBar', 'addPegoutCollateralButton', csrfToken));
document.getElementById('saveConfig').addEventListener('click', () => saveConfig(csrfToken, configurations));
document.getElementById('fetchSummariesButton').addEventListener('click', () => fetchSummariesReport(csrfToken));

populateConfigSection('generalConfig', configurations.general);
populateConfigSection('peginConfig', configurations.pegin);
Expand All @@ -591,4 +648,11 @@ document.addEventListener('DOMContentLoaded', () => {
fetchData('/pegin/collateral', 'peginCollateral', csrfToken);
fetchData('/pegout/collateral', 'pegoutCollateral', csrfToken);
checkFeeWarnings();

const today = new Date();
const lastMonth = new Date(today);
lastMonth.setMonth(today.getMonth() - 1);

document.getElementById('summaryStartDate').value = lastMonth.toISOString().split('T')[0];
document.getElementById('summaryEndDate').value = today.toISOString().split('T')[0];
});
Loading
Loading