mirror of
https://github.com/yzernik/squeaknode.git
synced 2026-08-13 12:33:25 +02:00
Paginate received payments (#1234)
* Add pagination to get received payments rpc * Add pagination to received payments frontend page * Comment unused method used for streaming in timeline page * Run frontend lint * Update frontend build
This commit is contained in:
parent
b9dad8ce0e
commit
b2858d714b
20 changed files with 169 additions and 48 deletions
|
|
@ -1,4 +1,4 @@
|
|||
import React, { useState, useEffect } from 'react';
|
||||
import React, { useState, useEffect, useCallback } from 'react';
|
||||
import {
|
||||
Grid,
|
||||
Button,
|
||||
|
|
@ -6,12 +6,14 @@ import {
|
|||
Tab,
|
||||
AppBar,
|
||||
Box,
|
||||
CircularProgress,
|
||||
} from '@material-ui/core';
|
||||
|
||||
// styles
|
||||
import { makeStyles } from '@material-ui/core/styles';
|
||||
|
||||
// components
|
||||
import ReplayIcon from '@material-ui/icons/Replay';
|
||||
import Widget from '../../components/Widget';
|
||||
import ReceivedPayment from '../../components/ReceivedPayment';
|
||||
|
||||
|
|
@ -30,10 +32,13 @@ const useStyles = makeStyles((theme) => ({
|
|||
},
|
||||
}));
|
||||
|
||||
const RECEIVED_PAYMENTS_PER_PAGE = 10;
|
||||
|
||||
export default function ReceivedPayments() {
|
||||
const classes = useStyles();
|
||||
const [value, setValue] = useState(0);
|
||||
const [receivedPayments, setReceivedPayments] = useState([]);
|
||||
const [waitingForReceivedPayments, setWaitingForReceivedPayments] = React.useState(false);
|
||||
|
||||
function a11yProps(index) {
|
||||
return {
|
||||
|
|
@ -46,9 +51,20 @@ export default function ReceivedPayments() {
|
|||
setValue(newValue);
|
||||
};
|
||||
|
||||
const loadReceivedPayments = () => {
|
||||
getReceivedPaymentsRequest((receivedPaymentsReply) => {
|
||||
setReceivedPayments(receivedPaymentsReply.getReceivedPaymentsList());
|
||||
const loadReceivedPayments = useCallback((limit, lastReceivedPayment) => {
|
||||
setWaitingForReceivedPayments(true);
|
||||
getReceivedPaymentsRequest(limit, lastReceivedPayment, handleLoadedReceivedPayments);
|
||||
},
|
||||
[]);
|
||||
|
||||
const handleLoadedReceivedPayments = (reply) => {
|
||||
const loadedReceivedPayments = reply.getReceivedPaymentsList();
|
||||
setWaitingForReceivedPayments(false);
|
||||
setReceivedPayments((prevReceivedPayments) => {
|
||||
if (!prevReceivedPayments) {
|
||||
return loadedReceivedPayments;
|
||||
}
|
||||
return prevReceivedPayments.concat(loadedReceivedPayments);
|
||||
});
|
||||
};
|
||||
|
||||
|
|
@ -59,8 +75,8 @@ export default function ReceivedPayments() {
|
|||
};
|
||||
|
||||
useEffect(() => {
|
||||
loadReceivedPayments();
|
||||
}, []);
|
||||
loadReceivedPayments(RECEIVED_PAYMENTS_PER_PAGE, null);
|
||||
}, [loadReceivedPayments]);
|
||||
|
||||
function TabPanel(props) {
|
||||
const {
|
||||
|
|
@ -118,7 +134,6 @@ export default function ReceivedPayments() {
|
|||
}
|
||||
|
||||
function ReceivedPaymentsContent() {
|
||||
console.log(`receivedPayments: ${receivedPayments}`);
|
||||
return (
|
||||
<>
|
||||
<Grid container spacing={4}>
|
||||
|
|
@ -153,10 +168,38 @@ export default function ReceivedPayments() {
|
|||
{PaymentsTabs()}
|
||||
</Grid>
|
||||
<Grid item xs={12} sm={3} />
|
||||
{ViewMoreReceivedPaymentsButton()}
|
||||
</Grid>
|
||||
);
|
||||
}
|
||||
|
||||
function ViewMoreReceivedPaymentsButton() {
|
||||
return (
|
||||
<>
|
||||
<Grid item xs={12}>
|
||||
<div className={classes.wrapper}>
|
||||
{!waitingForReceivedPayments
|
||||
&& (
|
||||
<Button
|
||||
variant="contained"
|
||||
color="primary"
|
||||
disabled={waitingForReceivedPayments}
|
||||
onClick={() => {
|
||||
const latestReceivedPayment = receivedPayments.slice(-1).pop();
|
||||
loadReceivedPayments(RECEIVED_PAYMENTS_PER_PAGE, latestReceivedPayment);
|
||||
}}
|
||||
>
|
||||
<ReplayIcon />
|
||||
View more squeaks
|
||||
</Button>
|
||||
)}
|
||||
{waitingForReceivedPayments && <CircularProgress size={48} className={classes.buttonProgress} />}
|
||||
</div>
|
||||
</Grid>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
{GridContent()}
|
||||
|
|
|
|||
|
|
@ -80,14 +80,14 @@ export default function TimelinePage() {
|
|||
});
|
||||
};
|
||||
|
||||
const handleLoadedNewSqueak = (newSqueak) => {
|
||||
setNewSqueaks((prevNewSqueaks) => {
|
||||
if (!prevNewSqueaks) {
|
||||
return [newSqueak];
|
||||
}
|
||||
return prevNewSqueaks.concat(newSqueak);
|
||||
});
|
||||
};
|
||||
// const handleLoadedNewSqueak = (newSqueak) => {
|
||||
// setNewSqueaks((prevNewSqueaks) => {
|
||||
// if (!prevNewSqueaks) {
|
||||
// return [newSqueak];
|
||||
// }
|
||||
// return prevNewSqueaks.concat(newSqueak);
|
||||
// });
|
||||
// };
|
||||
|
||||
useEffect(() => {
|
||||
getSqueaks(SQUEAKS_PER_PAGE, null);
|
||||
|
|
|
|||
|
|
@ -899,8 +899,10 @@ export function getSentPaymentsRequest(limit, lastSentPayment, handleResponse) {
|
|||
// });
|
||||
}
|
||||
|
||||
export function getReceivedPaymentsRequest(handleResponse) {
|
||||
export function getReceivedPaymentsRequest(limit, lastReceivedPayment, handleResponse) {
|
||||
const request = new GetReceivedPaymentsRequest();
|
||||
request.setLimit(limit);
|
||||
request.setLastReceivedPayment(lastReceivedPayment);
|
||||
makeRequest(
|
||||
'getreceivedpayments',
|
||||
request,
|
||||
|
|
|
|||
|
|
@ -664,7 +664,9 @@ def test_buy_squeak(
|
|||
|
||||
# Get the received payment from the seller node
|
||||
get_received_payments_response = admin_stub.GetReceivedPayments(
|
||||
squeak_admin_pb2.GetReceivedPaymentsRequest(),
|
||||
squeak_admin_pb2.GetReceivedPaymentsRequest(
|
||||
limit=100,
|
||||
),
|
||||
)
|
||||
# print(
|
||||
# "get_received_payments_response: {}".format(
|
||||
|
|
|
|||
|
|
@ -927,6 +927,11 @@ message SentOffer {
|
|||
}
|
||||
|
||||
message GetReceivedPaymentsRequest {
|
||||
/// Limit number of results
|
||||
int32 limit = 1;
|
||||
|
||||
/// Last entry
|
||||
ReceivedPayment last_received_payment = 2;
|
||||
}
|
||||
|
||||
message GetReceivedPaymentsReply {
|
||||
|
|
|
|||
|
|
@ -234,3 +234,15 @@ def message_to_sent_payment(sent_payment: squeak_admin_pb2.SentPayment) -> SentP
|
|||
node_pubkey=sent_payment.node_pubkey,
|
||||
valid=sent_payment.valid,
|
||||
)
|
||||
|
||||
|
||||
def message_to_received_payment(received_payment: squeak_admin_pb2.ReceivedPayment) -> ReceivedPayment:
|
||||
return ReceivedPayment(
|
||||
received_payment_id=received_payment.received_payment_id,
|
||||
created_time_ms=received_payment.time_ms,
|
||||
squeak_hash=bytes.fromhex(received_payment.squeak_hash),
|
||||
payment_hash=bytes.fromhex(received_payment.payment_hash),
|
||||
price_msat=received_payment.price_msat,
|
||||
settle_index=0, # TODO: This is not correct, fix later.
|
||||
peer_address=message_to_peer_address(received_payment.peer_address),
|
||||
)
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ import logging
|
|||
from proto import squeak_admin_pb2
|
||||
from squeaknode.admin.messages import connected_peer_to_message
|
||||
from squeaknode.admin.messages import message_to_peer_address
|
||||
from squeaknode.admin.messages import message_to_received_payment
|
||||
from squeaknode.admin.messages import message_to_sent_payment
|
||||
from squeaknode.admin.messages import message_to_squeak_entry
|
||||
from squeaknode.admin.messages import offer_entry_to_message
|
||||
|
|
@ -698,8 +699,25 @@ class SqueakAdminServerHandler(object):
|
|||
)
|
||||
|
||||
def handle_get_received_payments(self, request):
|
||||
logger.info("Handle get received payments")
|
||||
received_payments = self.squeak_controller.get_received_payments()
|
||||
limit = request.limit
|
||||
last_received_payment = message_to_received_payment(request.last_received_payment) if request.HasField(
|
||||
"last_received_payment") else None
|
||||
logger.info("""Handle get received payments with
|
||||
limit: {}
|
||||
last_received_payment: {}
|
||||
""".format(
|
||||
limit,
|
||||
last_received_payment,
|
||||
))
|
||||
received_payments = self.squeak_controller.get_received_payments(
|
||||
limit,
|
||||
last_received_payment,
|
||||
)
|
||||
logger.info(
|
||||
"Got number of received payments: {}".format(
|
||||
len(received_payments)
|
||||
)
|
||||
)
|
||||
received_payment_msgs = [
|
||||
received_payments_to_message(received_payment)
|
||||
for received_payment in received_payments
|
||||
|
|
|
|||
|
|
@ -1,17 +1,17 @@
|
|||
{
|
||||
"files": {
|
||||
"main.js": "/static/js/main.79916aed.chunk.js",
|
||||
"main.js.map": "/static/js/main.79916aed.chunk.js.map",
|
||||
"main.js": "/static/js/main.b5dd81a1.chunk.js",
|
||||
"main.js.map": "/static/js/main.b5dd81a1.chunk.js.map",
|
||||
"runtime-main.js": "/static/js/runtime-main.9f0ba400.js",
|
||||
"runtime-main.js.map": "/static/js/runtime-main.9f0ba400.js.map",
|
||||
"static/css/2.ea4ba2f0.chunk.css": "/static/css/2.ea4ba2f0.chunk.css",
|
||||
"static/js/2.e1ce3d4b.chunk.js": "/static/js/2.e1ce3d4b.chunk.js",
|
||||
"static/js/2.e1ce3d4b.chunk.js.map": "/static/js/2.e1ce3d4b.chunk.js.map",
|
||||
"static/js/2.4181937e.chunk.js": "/static/js/2.4181937e.chunk.js",
|
||||
"static/js/2.4181937e.chunk.js.map": "/static/js/2.4181937e.chunk.js.map",
|
||||
"index.html": "/index.html",
|
||||
"precache-manifest.aefedce4f358985ca90741faf5431bc5.js": "/precache-manifest.aefedce4f358985ca90741faf5431bc5.js",
|
||||
"precache-manifest.8a0c063712e93bdb27b968958cbb7b2b.js": "/precache-manifest.8a0c063712e93bdb27b968958cbb7b2b.js",
|
||||
"service-worker.js": "/service-worker.js",
|
||||
"static/css/2.ea4ba2f0.chunk.css.map": "/static/css/2.ea4ba2f0.chunk.css.map",
|
||||
"static/js/2.e1ce3d4b.chunk.js.LICENSE.txt": "/static/js/2.e1ce3d4b.chunk.js.LICENSE.txt",
|
||||
"static/js/2.4181937e.chunk.js.LICENSE.txt": "/static/js/2.4181937e.chunk.js.LICENSE.txt",
|
||||
"static/media/font-awesome.min.css": "/static/media/fontawesome-webfont.fee66e71.woff",
|
||||
"static/media/google.svg": "/static/media/google.695a3160.svg",
|
||||
"static/media/logo.svg": "/static/media/logo.a0185b04.svg"
|
||||
|
|
@ -19,7 +19,7 @@
|
|||
"entrypoints": [
|
||||
"static/js/runtime-main.9f0ba400.js",
|
||||
"static/css/2.ea4ba2f0.chunk.css",
|
||||
"static/js/2.e1ce3d4b.chunk.js",
|
||||
"static/js/main.79916aed.chunk.js"
|
||||
"static/js/2.4181937e.chunk.js",
|
||||
"static/js/main.b5dd81a1.chunk.js"
|
||||
]
|
||||
}
|
||||
|
|
@ -1 +1 @@
|
|||
<!doctype html><html lang="en"><head><meta charset="utf-8"/><link rel="shortcut icon" href="/favicon.ico"/><meta name="viewport" content="width=device-width,initial-scale=1,shrink-to-fit=no"/><meta name="theme-color" content="#000000"/><link rel="manifest" href="/manifest.json"/><title>Squeak Node</title><meta name="description" content="Squeak Node is a frontend for accessing a squeak node"><meta name="keywords" content="squeak, bitcoin, lightning"><meta name="author" content="Flatlogic LLC."><link href="/static/css/2.ea4ba2f0.chunk.css" rel="stylesheet"></head><body style="font-family:Roboto,sans-serif"><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div><script>!function(e){function r(r){for(var n,f,l=r[0],a=r[1],i=r[2],c=0,s=[];c<l.length;c++)f=l[c],Object.prototype.hasOwnProperty.call(o,f)&&o[f]&&s.push(o[f][0]),o[f]=0;for(n in a)Object.prototype.hasOwnProperty.call(a,n)&&(e[n]=a[n]);for(p&&p(r);s.length;)s.shift()();return u.push.apply(u,i||[]),t()}function t(){for(var e,r=0;r<u.length;r++){for(var t=u[r],n=!0,l=1;l<t.length;l++){var a=t[l];0!==o[a]&&(n=!1)}n&&(u.splice(r--,1),e=f(f.s=t[0]))}return e}var n={},o={1:0},u=[];function f(r){if(n[r])return n[r].exports;var t=n[r]={i:r,l:!1,exports:{}};return e[r].call(t.exports,t,t.exports,f),t.l=!0,t.exports}f.m=e,f.c=n,f.d=function(e,r,t){f.o(e,r)||Object.defineProperty(e,r,{enumerable:!0,get:t})},f.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},f.t=function(e,r){if(1&r&&(e=f(e)),8&r)return e;if(4&r&&"object"==typeof e&&e&&e.__esModule)return e;var t=Object.create(null);if(f.r(t),Object.defineProperty(t,"default",{enumerable:!0,value:e}),2&r&&"string"!=typeof e)for(var n in e)f.d(t,n,function(r){return e[r]}.bind(null,n));return t},f.n=function(e){var r=e&&e.__esModule?function(){return e.default}:function(){return e};return f.d(r,"a",r),r},f.o=function(e,r){return Object.prototype.hasOwnProperty.call(e,r)},f.p="/";var l=this["webpackJsonpsqueak-node-frontend"]=this["webpackJsonpsqueak-node-frontend"]||[],a=l.push.bind(l);l.push=r,l=l.slice();for(var i=0;i<l.length;i++)r(l[i]);var p=a;t()}([])</script><script src="/static/js/2.e1ce3d4b.chunk.js"></script><script src="/static/js/main.79916aed.chunk.js"></script></body></html>
|
||||
<!doctype html><html lang="en"><head><meta charset="utf-8"/><link rel="shortcut icon" href="/favicon.ico"/><meta name="viewport" content="width=device-width,initial-scale=1,shrink-to-fit=no"/><meta name="theme-color" content="#000000"/><link rel="manifest" href="/manifest.json"/><title>Squeak Node</title><meta name="description" content="Squeak Node is a frontend for accessing a squeak node"><meta name="keywords" content="squeak, bitcoin, lightning"><meta name="author" content="Flatlogic LLC."><link href="/static/css/2.ea4ba2f0.chunk.css" rel="stylesheet"></head><body style="font-family:Roboto,sans-serif"><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div><script>!function(e){function r(r){for(var n,f,l=r[0],a=r[1],i=r[2],c=0,s=[];c<l.length;c++)f=l[c],Object.prototype.hasOwnProperty.call(o,f)&&o[f]&&s.push(o[f][0]),o[f]=0;for(n in a)Object.prototype.hasOwnProperty.call(a,n)&&(e[n]=a[n]);for(p&&p(r);s.length;)s.shift()();return u.push.apply(u,i||[]),t()}function t(){for(var e,r=0;r<u.length;r++){for(var t=u[r],n=!0,l=1;l<t.length;l++){var a=t[l];0!==o[a]&&(n=!1)}n&&(u.splice(r--,1),e=f(f.s=t[0]))}return e}var n={},o={1:0},u=[];function f(r){if(n[r])return n[r].exports;var t=n[r]={i:r,l:!1,exports:{}};return e[r].call(t.exports,t,t.exports,f),t.l=!0,t.exports}f.m=e,f.c=n,f.d=function(e,r,t){f.o(e,r)||Object.defineProperty(e,r,{enumerable:!0,get:t})},f.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},f.t=function(e,r){if(1&r&&(e=f(e)),8&r)return e;if(4&r&&"object"==typeof e&&e&&e.__esModule)return e;var t=Object.create(null);if(f.r(t),Object.defineProperty(t,"default",{enumerable:!0,value:e}),2&r&&"string"!=typeof e)for(var n in e)f.d(t,n,function(r){return e[r]}.bind(null,n));return t},f.n=function(e){var r=e&&e.__esModule?function(){return e.default}:function(){return e};return f.d(r,"a",r),r},f.o=function(e,r){return Object.prototype.hasOwnProperty.call(e,r)},f.p="/";var l=this["webpackJsonpsqueak-node-frontend"]=this["webpackJsonpsqueak-node-frontend"]||[],a=l.push.bind(l);l.push=r,l=l.slice();for(var i=0;i<l.length;i++)r(l[i]);var p=a;t()}([])</script><script src="/static/js/2.4181937e.chunk.js"></script><script src="/static/js/main.b5dd81a1.chunk.js"></script></body></html>
|
||||
|
|
@ -1,23 +1,23 @@
|
|||
self.__precacheManifest = (self.__precacheManifest || []).concat([
|
||||
{
|
||||
"revision": "c902aa1bcd9c91e45badf061208b8637",
|
||||
"revision": "47dabe8d9a77cca2c8d5407e18931825",
|
||||
"url": "/index.html"
|
||||
},
|
||||
{
|
||||
"revision": "785caac4a07b948d3be4",
|
||||
"revision": "f1e946917c419318e8ac",
|
||||
"url": "/static/css/2.ea4ba2f0.chunk.css"
|
||||
},
|
||||
{
|
||||
"revision": "785caac4a07b948d3be4",
|
||||
"url": "/static/js/2.e1ce3d4b.chunk.js"
|
||||
"revision": "f1e946917c419318e8ac",
|
||||
"url": "/static/js/2.4181937e.chunk.js"
|
||||
},
|
||||
{
|
||||
"revision": "279b8724b89bf7d504758b3fa917239f",
|
||||
"url": "/static/js/2.e1ce3d4b.chunk.js.LICENSE.txt"
|
||||
"url": "/static/js/2.4181937e.chunk.js.LICENSE.txt"
|
||||
},
|
||||
{
|
||||
"revision": "79092192931dd8817290",
|
||||
"url": "/static/js/main.79916aed.chunk.js"
|
||||
"revision": "519826351c7336fbd239",
|
||||
"url": "/static/js/main.b5dd81a1.chunk.js"
|
||||
},
|
||||
{
|
||||
"revision": "cc9816de5a8639d377ea",
|
||||
|
|
@ -14,7 +14,7 @@
|
|||
importScripts("https://storage.googleapis.com/workbox-cdn/releases/4.3.1/workbox-sw.js");
|
||||
|
||||
importScripts(
|
||||
"/precache-manifest.aefedce4f358985ca90741faf5431bc5.js"
|
||||
"/precache-manifest.8a0c063712e93bdb27b968958cbb7b2b.js"
|
||||
);
|
||||
|
||||
self.addEventListener('message', (event) => {
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
|
@ -1221,10 +1221,41 @@ class SqueakDb:
|
|||
except sqlalchemy.exc.IntegrityError:
|
||||
raise DuplicateReceivedPaymentError()
|
||||
|
||||
def get_received_payments(self) -> List[ReceivedPayment]:
|
||||
def get_received_payments(
|
||||
self,
|
||||
limit: int,
|
||||
last_received_payment: Optional[ReceivedPayment],
|
||||
) -> List[ReceivedPayment]:
|
||||
""" Get all received payments. """
|
||||
s = select([self.received_payments]).order_by(
|
||||
self.received_payments.c.created_time_ms.desc(),
|
||||
last_created_time = last_received_payment.created_time_ms if last_received_payment else self.timestamp_now_ms
|
||||
last_payment_hash = last_received_payment.payment_hash if last_received_payment else MAX_HASH
|
||||
logger.info("""Get received payments db query with
|
||||
limit: {}
|
||||
last_created_time: {}
|
||||
last_payment_hash: {}
|
||||
""".format(
|
||||
limit,
|
||||
last_created_time,
|
||||
last_payment_hash.hex(),
|
||||
))
|
||||
s = (
|
||||
select([self.received_payments])
|
||||
.order_by(
|
||||
)
|
||||
.where(
|
||||
tuple_(
|
||||
self.received_payments.c.created_time_ms,
|
||||
self.received_payments.c.payment_hash,
|
||||
) < tuple_(
|
||||
last_created_time,
|
||||
last_payment_hash,
|
||||
)
|
||||
)
|
||||
.order_by(
|
||||
self.received_payments.c.created_time_ms.desc(),
|
||||
self.received_payments.c.payment_hash.desc(),
|
||||
)
|
||||
.limit(limit)
|
||||
)
|
||||
with self.get_connection() as connection:
|
||||
result = connection.execute(s)
|
||||
|
|
|
|||
|
|
@ -42,6 +42,7 @@ from squeaknode.core.block_range import BlockRange
|
|||
from squeaknode.core.offer import Offer
|
||||
from squeaknode.core.peer_address import PeerAddress
|
||||
from squeaknode.core.received_offer import ReceivedOffer
|
||||
from squeaknode.core.received_payment import ReceivedPayment
|
||||
from squeaknode.core.received_payment_summary import ReceivedPaymentSummary
|
||||
from squeaknode.core.sent_offer import SentOffer
|
||||
from squeaknode.core.sent_payment import SentPayment
|
||||
|
|
@ -431,8 +432,15 @@ class SqueakController:
|
|||
def get_sent_offers(self):
|
||||
return self.squeak_db.get_sent_offers()
|
||||
|
||||
def get_received_payments(self):
|
||||
return self.squeak_db.get_received_payments()
|
||||
def get_received_payments(
|
||||
self,
|
||||
limit: int,
|
||||
last_received_payment: Optional[ReceivedPayment],
|
||||
) -> List[ReceivedPayment]:
|
||||
return self.squeak_db.get_received_payments(
|
||||
limit,
|
||||
last_received_payment,
|
||||
)
|
||||
|
||||
def delete_all_expired_received_offers(self):
|
||||
num_expired_received_offers = self.squeak_db.delete_expired_received_offers()
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue