Add received payments table and get it in rpc method (#443)

This commit is contained in:
Jonathan Zernik 2020-11-11 03:04:09 -05:00 committed by GitHub
parent f7c5fabe43
commit 0dde62bf46
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 181 additions and 0 deletions

View file

@ -0,0 +1,38 @@
"""Add received_payment table
Revision ID: 387dd872e766
Revises: ccc641c2ce52
Create Date: 2020-11-11 01:24:10.148710
"""
from alembic import op
import sqlalchemy as sa
# revision identifiers, used by Alembic.
revision = '387dd872e766'
down_revision = 'ccc641c2ce52'
branch_labels = None
depends_on = None
def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.create_table('received_payment',
sa.Column('received_payment_id', sa.Integer(), nullable=False),
sa.Column('created', sa.DateTime(), server_default=sa.text('(CURRENT_TIMESTAMP)'), nullable=False),
sa.Column('squeak_hash', sa.String(length=64), nullable=False),
sa.Column('preimage_hash', sa.String(length=64), nullable=False),
sa.Column('price_msat', sa.Integer(), nullable=False),
sa.Column('is_paid', sa.Boolean(), nullable=False),
sa.Column('payment_time', sa.DateTime(), nullable=True),
sa.PrimaryKeyConstraint('received_payment_id'),
sa.UniqueConstraint('preimage_hash')
)
# ### end Alembic commands ###
def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.drop_table('received_payment')
# ### end Alembic commands ###

View file

@ -913,6 +913,13 @@ def test_connect_other_node(server_stub, admin_stub, other_server_stub, other_ad
assert sent_payment_time > datetime.datetime.now() - five_minutes
assert sent_payment_time < datetime.datetime.now()
# Get the received payment from the seller node
get_received_payments_response = admin_stub.GetReceivedPayments(
squeak_admin_pb2.GetReceivedPaymentsRequest(),
)
squeak_hashes = [received_payment.squeak_hash for received_payment in get_received_payments_response.received_payments]
assert saved_squeak_hash in squeak_hashes
def test_download_single_squeak(server_stub, admin_stub, other_server_stub, other_admin_stub, lightning_client, signing_profile_id, saved_squeak_hash):

View file

@ -180,6 +180,10 @@ service SqueakAdmin {
*/
rpc GetSqueakDetails (GetSqueakDetailsRequest) returns (GetSqueakDetailsReply) {}
/** sqkadmin: `getreceivedpayments`
*/
rpc GetReceivedPayments (GetReceivedPaymentsRequest) returns (GetReceivedPaymentsReply) {}
}
message CreateSigningProfileRequest {
@ -645,3 +649,31 @@ message SqueakDetailEntry {
/// The seriallized squeak in hex encoding
string serialized_squeak_hex = 1;
}
message GetReceivedPaymentsRequest {
}
message GetReceivedPaymentsReply {
/// The received payments
repeated ReceivedPayment received_payments = 1;
}
message ReceivedPayment {
/// The received payment id
int32 received_payment_id = 1;
/// The squeak hash
string squeak_hash = 2;
/// The preimage hash
string preimage_hash = 3;
/// The price_msat
int64 price_msat = 4;
/// Is the payment paid
bool is_paid = 5;
/// Time of payment
int64 payment_time_ms = 6;
}

View file

@ -11,6 +11,7 @@ from squeaknode.admin.util import offer_entry_to_message
from squeaknode.admin.util import sent_payment_with_peer_to_message
from squeaknode.admin.util import sync_result_to_message
from squeaknode.admin.util import squeak_entry_to_detail_message
from squeaknode.admin.util import received_payment_to_message
from proto import squeak_admin_pb2, squeak_admin_pb2_grpc
@ -415,3 +416,12 @@ class SqueakAdminServerHandler(object):
return squeak_admin_pb2.GetSqueakDetailsReply(
squeak_detail_entry=detail_message
)
def handle_get_received_payments(self, request):
logger.info("Handle get received payments")
received_payments = self.squeak_node.get_received_payments()
logger.info("Received payments: {}".format(received_payments))
received_payment_msgs = [received_payment_to_message(received_payment) for received_payment in received_payments]
return squeak_admin_pb2.GetReceivedPaymentsReply(
received_payments=received_payment_msgs,
)

View file

@ -154,6 +154,9 @@ class SqueakAdminServerServicer(squeak_admin_pb2_grpc.SqueakAdminServicer):
def GetSqueakDetails(self, request, context):
return self.handler.handle_get_squeak_details(request)
def GetReceivedPayments(self, request, context):
return self.handler.handle_get_received_payments(request)
def serve(self):
server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
squeak_admin_pb2_grpc.add_SqueakAdminServicer_to_server(self, server)

View file

@ -120,3 +120,17 @@ def squeak_entry_to_detail_message(squeak_entry_with_profile):
return squeak_admin_pb2.SqueakDetailEntry(
serialized_squeak_hex=serialized_squeak.hex(),
)
def received_payment_to_message(received_payment):
if received_payment is None:
return None
return squeak_admin_pb2.ReceivedPayment(
received_payment_id=received_payment.received_payment_id,
squeak_hash=received_payment.squeak_hash,
preimage_hash=received_payment.preimage_hash,
price_msat=received_payment.price_msat,
is_paid=received_payment.is_paid,
payment_time_ms=int(received_payment.payment_time.timestamp()) * 1000
if received_payment.payment_time
else None,
)

View file

@ -108,3 +108,15 @@ class Models:
Column("node_pubkey", String(66), nullable=False),
Column("preimage_is_valid", Boolean, nullable=False),
)
self.received_payments = Table(
"received_payment",
self.metadata,
Column("received_payment_id", Integer, primary_key=True),
Column("created", DateTime, server_default=func.now(), nullable=False),
Column("squeak_hash", String(64), nullable=False),
Column("preimage_hash", String(64), unique=True, nullable=False),
Column("price_msat", Integer, nullable=False, default=0),
Column("is_paid", Boolean, nullable=False),
Column("payment_time", DateTime, nullable=True),
)

View file

@ -28,6 +28,7 @@ from squeaknode.core.squeak_entry_with_profile import SqueakEntryWithProfile
from squeaknode.server.squeak_peer import SqueakPeer
from squeaknode.server.squeak_profile import SqueakProfile
from squeaknode.server.sent_payment import SentPayment
from squeaknode.server.received_payment import ReceivedPayment
from squeaknode.server.util import get_hash
from squeaknode.db.models import Models
from squeaknode.db.migrations import run_migrations
@ -80,6 +81,10 @@ class SqueakDb:
def sent_payments(self):
return self.models.sent_payments
@property
def received_payments(self):
return self.models.received_payments
def insert_squeak(self, squeak):
""" Insert a new squeak. """
vch_decryption_key = squeak.GetDecryptionKey().get_bytes() if squeak.HasDecryptionKey() else None
@ -927,6 +932,33 @@ class SqueakDb:
row = result.fetchone()
return self._parse_sent_payment_with_peer(row)
def insert_received_payment(self, received_payment):
""" Insert a new received payment. """
ins = self.received_payments.insert().values(
squeak_hash=received_payment.squeak_hash,
preimage_hash=received_payment.preimage_hash,
price_msat=received_payment.price_msat,
is_paid=received_payment.is_paid,
)
with self.get_connection() as connection:
res = connection.execute(ins)
received_payment_id = res.inserted_primary_key[0]
return received_payment_id
def get_received_payments(self):
""" Get all received payments. """
s = (
select([self.received_payments])
.order_by(
self.received_payments.c.created.desc(),
)
)
with self.get_connection() as connection:
result = connection.execute(s)
rows = result.fetchall()
received_payments = [self._parse_received_payment(row) for row in rows]
return received_payments
def _parse_squeak_entry(self, row):
if row is None:
return None
@ -1037,3 +1069,15 @@ class SqueakDb:
sent_payment=sent_payment,
peer=peer,
)
def _parse_received_payment(self, row):
if row is None:
return None
return ReceivedPayment(
received_payment_id=row["received_payment_id"],
squeak_hash=row["squeak_hash"],
preimage_hash=row["preimage_hash"],
price_msat=row["price_msat"],
is_paid=row["is_paid"],
payment_time=row["payment_time"],
)

View file

@ -21,6 +21,7 @@ from squeaknode.node.squeak_store import SqueakStore
from squeaknode.node.squeak_sync_status import SqueakSyncController
from squeaknode.node.squeak_whitelist import SqueakWhitelist
from squeaknode.server.buy_offer import BuyOffer
from squeaknode.server.received_payment import ReceivedPayment
from squeaknode.server.squeak_peer import SqueakPeer
from squeaknode.server.squeak_profile import SqueakProfile
from squeaknode.server.sent_payment import SentPayment
@ -131,6 +132,17 @@ class SqueakNode:
# Get the lightning network node pubkey
get_info_response = self.lightning_client.get_info()
pubkey = get_info_response.identity_pubkey
# Save the incoming potential payment in the databse.
self.squeak_db.insert_received_payment(
ReceivedPayment(
received_payment_id=None,
squeak_hash=squeak_hash,
preimage_hash=preimage_hash.hex(),
price_msat=self.price_msat,
is_paid=False,
payment_time=None,
)
)
# Return the buy offer
return BuyOffer(
squeak_hash,
@ -336,3 +348,6 @@ class SqueakNode:
def get_sent_payment(self, sent_payment_id):
return self.squeak_db.get_sent_payment(sent_payment_id)
def get_received_payments(self):
return self.squeak_db.get_received_payments()

View file

@ -0,0 +1,6 @@
from collections import namedtuple
ReceivedPayment = namedtuple(
"ReceivedPayment",
"received_payment_id, squeak_hash, preimage_hash, price_msat, is_paid, payment_time",
)