From 1ee2a15c76adcf80b55f1f0b1674b3918b0f3a30 Mon Sep 17 00:00:00 2001 From: michael1011 Date: Tue, 5 Mar 2024 20:03:04 +0100 Subject: [PATCH] feat: mpay response compatibility with pay --- lib/VersionCheck.ts | 4 +- lib/proto/mpay/mpay_pb.d.ts | 18 ++ lib/proto/mpay/mpay_pb.js | 182 +++++++++++++++++++- tools/plugins/hold/protos/hold_pb2.py | 2 +- tools/plugins/mpay/pay/mpay.py | 15 +- tools/plugins/mpay/pay/sendpay.py | 27 ++- tools/plugins/mpay/protos/mpay.proto | 6 + tools/plugins/mpay/protos/mpay_pb2.py | 20 +-- tools/plugins/mpay/protos/mpay_pb2.pyi | 16 +- tools/plugins/mpay/rpc/server.py | 6 + tools/plugins/mpay/rpc/tests/test_server.py | 18 +- 11 files changed, 291 insertions(+), 23 deletions(-) diff --git a/lib/VersionCheck.ts b/lib/VersionCheck.ts index 93a68db8..2fff0e1c 100644 --- a/lib/VersionCheck.ts +++ b/lib/VersionCheck.ts @@ -87,11 +87,11 @@ class VersionCheck { }, [ClnClient.serviceNameHold]: { minimal: '0.0.3', - maximal: '0.0.4', + maximal: '0.0.5', }, [MpayClient.serviceName]: { minimal: '0.1.0', - maximal: '0.1.0', + maximal: '0.1.1', }, [LndClient.serviceName]: { minimal: '0.16.0', diff --git a/lib/proto/mpay/mpay_pb.d.ts b/lib/proto/mpay/mpay_pb.d.ts index 82fbe51f..a4be4c36 100644 --- a/lib/proto/mpay/mpay_pb.d.ts +++ b/lib/proto/mpay/mpay_pb.d.ts @@ -379,6 +379,18 @@ export class PayResponse extends jspb.Message { setFeeMsat(value: number): PayResponse; getTime(): number; setTime(value: number): PayResponse; + getDestination(): string; + setDestination(value: string): PayResponse; + getAmountMsat(): number; + setAmountMsat(value: number): PayResponse; + getAmountSentMsat(): number; + setAmountSentMsat(value: number): PayResponse; + getParts(): number; + setParts(value: number): PayResponse; + getStatus(): string; + setStatus(value: string): PayResponse; + getCreatedAt(): number; + setCreatedAt(value: number): PayResponse; serializeBinary(): Uint8Array; toObject(includeInstance?: boolean): PayResponse.AsObject; @@ -396,6 +408,12 @@ export namespace PayResponse { paymentPreimage: string, feeMsat: number, time: number, + destination: string, + amountMsat: number, + amountSentMsat: number, + parts: number, + status: string, + createdAt: number, } } diff --git a/lib/proto/mpay/mpay_pb.js b/lib/proto/mpay/mpay_pb.js index 02cbb5d0..79025791 100644 --- a/lib/proto/mpay/mpay_pb.js +++ b/lib/proto/mpay/mpay_pb.js @@ -2945,7 +2945,13 @@ proto.mpay.PayResponse.toObject = function(includeInstance, msg) { paymentHash: jspb.Message.getFieldWithDefault(msg, 1, ""), paymentPreimage: jspb.Message.getFieldWithDefault(msg, 2, ""), feeMsat: jspb.Message.getFieldWithDefault(msg, 3, 0), - time: jspb.Message.getFieldWithDefault(msg, 4, 0) + time: jspb.Message.getFieldWithDefault(msg, 4, 0), + destination: jspb.Message.getFieldWithDefault(msg, 5, ""), + amountMsat: jspb.Message.getFieldWithDefault(msg, 6, 0), + amountSentMsat: jspb.Message.getFieldWithDefault(msg, 7, 0), + parts: jspb.Message.getFieldWithDefault(msg, 8, 0), + status: jspb.Message.getFieldWithDefault(msg, 9, ""), + createdAt: jspb.Message.getFieldWithDefault(msg, 10, 0) }; if (includeInstance) { @@ -2998,6 +3004,30 @@ proto.mpay.PayResponse.deserializeBinaryFromReader = function(msg, reader) { var value = /** @type {number} */ (reader.readUint64()); msg.setTime(value); break; + case 5: + var value = /** @type {string} */ (reader.readString()); + msg.setDestination(value); + break; + case 6: + var value = /** @type {number} */ (reader.readUint64()); + msg.setAmountMsat(value); + break; + case 7: + var value = /** @type {number} */ (reader.readUint64()); + msg.setAmountSentMsat(value); + break; + case 8: + var value = /** @type {number} */ (reader.readUint32()); + msg.setParts(value); + break; + case 9: + var value = /** @type {string} */ (reader.readString()); + msg.setStatus(value); + break; + case 10: + var value = /** @type {number} */ (reader.readUint64()); + msg.setCreatedAt(value); + break; default: reader.skipField(); break; @@ -3055,6 +3085,48 @@ proto.mpay.PayResponse.serializeBinaryToWriter = function(message, writer) { f ); } + f = message.getDestination(); + if (f.length > 0) { + writer.writeString( + 5, + f + ); + } + f = message.getAmountMsat(); + if (f !== 0) { + writer.writeUint64( + 6, + f + ); + } + f = message.getAmountSentMsat(); + if (f !== 0) { + writer.writeUint64( + 7, + f + ); + } + f = message.getParts(); + if (f !== 0) { + writer.writeUint32( + 8, + f + ); + } + f = message.getStatus(); + if (f.length > 0) { + writer.writeString( + 9, + f + ); + } + f = message.getCreatedAt(); + if (f !== 0) { + writer.writeUint64( + 10, + f + ); + } }; @@ -3130,6 +3202,114 @@ proto.mpay.PayResponse.prototype.setTime = function(value) { }; +/** + * optional string destination = 5; + * @return {string} + */ +proto.mpay.PayResponse.prototype.getDestination = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 5, "")); +}; + + +/** + * @param {string} value + * @return {!proto.mpay.PayResponse} returns this + */ +proto.mpay.PayResponse.prototype.setDestination = function(value) { + return jspb.Message.setProto3StringField(this, 5, value); +}; + + +/** + * optional uint64 amount_msat = 6; + * @return {number} + */ +proto.mpay.PayResponse.prototype.getAmountMsat = function() { + return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 6, 0)); +}; + + +/** + * @param {number} value + * @return {!proto.mpay.PayResponse} returns this + */ +proto.mpay.PayResponse.prototype.setAmountMsat = function(value) { + return jspb.Message.setProto3IntField(this, 6, value); +}; + + +/** + * optional uint64 amount_sent_msat = 7; + * @return {number} + */ +proto.mpay.PayResponse.prototype.getAmountSentMsat = function() { + return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 7, 0)); +}; + + +/** + * @param {number} value + * @return {!proto.mpay.PayResponse} returns this + */ +proto.mpay.PayResponse.prototype.setAmountSentMsat = function(value) { + return jspb.Message.setProto3IntField(this, 7, value); +}; + + +/** + * optional uint32 parts = 8; + * @return {number} + */ +proto.mpay.PayResponse.prototype.getParts = function() { + return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 8, 0)); +}; + + +/** + * @param {number} value + * @return {!proto.mpay.PayResponse} returns this + */ +proto.mpay.PayResponse.prototype.setParts = function(value) { + return jspb.Message.setProto3IntField(this, 8, value); +}; + + +/** + * optional string status = 9; + * @return {string} + */ +proto.mpay.PayResponse.prototype.getStatus = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 9, "")); +}; + + +/** + * @param {string} value + * @return {!proto.mpay.PayResponse} returns this + */ +proto.mpay.PayResponse.prototype.setStatus = function(value) { + return jspb.Message.setProto3StringField(this, 9, value); +}; + + +/** + * optional uint64 created_at = 10; + * @return {number} + */ +proto.mpay.PayResponse.prototype.getCreatedAt = function() { + return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 10, 0)); +}; + + +/** + * @param {number} value + * @return {!proto.mpay.PayResponse} returns this + */ +proto.mpay.PayResponse.prototype.setCreatedAt = function(value) { + return jspb.Message.setProto3IntField(this, 10, value); +}; + + diff --git a/tools/plugins/hold/protos/hold_pb2.py b/tools/plugins/hold/protos/hold_pb2.py index 9b9838af..27ccbe54 100644 --- a/tools/plugins/hold/protos/hold_pb2.py +++ b/tools/plugins/hold/protos/hold_pb2.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- # Generated by the protocol buffer compiler. DO NOT EDIT! # source: hold.proto -# Protobuf Python Version: 4.25.0 +# Protobuf Python Version: 4.25.1 """Generated protocol buffer code.""" from google.protobuf import descriptor as _descriptor from google.protobuf import descriptor_pool as _descriptor_pool diff --git a/tools/plugins/mpay/pay/mpay.py b/tools/plugins/mpay/pay/mpay.py index 9cb553ac..a97d09ed 100644 --- a/tools/plugins/mpay/pay/mpay.py +++ b/tools/plugins/mpay/pay/mpay.py @@ -10,7 +10,7 @@ from plugins.mpay.pay.excludes import Excludes, ExcludesPayment from plugins.mpay.pay.invoice_check import InvoiceChecker from plugins.mpay.pay.payer import Payer -from plugins.mpay.pay.sendpay import PaymentHelper, PaymentResult +from plugins.mpay.pay.sendpay import STATUS_COMPLETE, PaymentHelper, PaymentResult from plugins.mpay.utils import fee_with_percent, format_error @@ -110,12 +110,19 @@ def _check_for_paid(self, payment_hash: str) -> PaymentResult | None: if len(res) == 0: return None + amount = Millisatoshi(sum(int(pay["amount_msat"]) for pay in res)) + amount_sent = Millisatoshi(sum(int(pay["amount_sent_msat"]) for pay in res)) + return PaymentResult( + destination=res[0]["destination"], payment_hash=payment_hash, payment_preimage=res[0]["preimage"], - fee_msat=Millisatoshi( - sum(int(pay["amount_sent_msat"]) - int(pay["amount_msat"]) for pay in res) - ), + parts=len(res), + amount_msat=amount, + amount_sent_msat=amount_sent, + fee_msat=amount_sent - amount, + status=STATUS_COMPLETE, + created_at=res[0]["created_at"], time=0, ) diff --git a/tools/plugins/mpay/pay/sendpay.py b/tools/plugins/mpay/pay/sendpay.py index 3ff3ceba..8829e39a 100644 --- a/tools/plugins/mpay/pay/sendpay.py +++ b/tools/plugins/mpay/pay/sendpay.py @@ -8,13 +8,25 @@ PERMANENT_ERRORS = ["WIRE_INCORRECT_OR_UNKNOWN_PAYMENT_DETAILS"] +STATUS_COMPLETE = "complete" + @dataclass class PaymentResult: + destination: str + payment_hash: str payment_preimage: str + + amount_msat: Millisatoshi + amount_sent_msat: Millisatoshi + + parts: int + status: str fee_msat: Millisatoshi + time: int + created_at: int def to_dict(self) -> dict[str, Any]: return {k: int(v) if isinstance(v, Millisatoshi) else v for k, v in self.__dict__.items()} @@ -67,11 +79,22 @@ def send(self, route: Route, bolt11: str, decoded: dict[str, Any]) -> PaymentRes try: wait = self._pl.rpc.waitsendpay(pay["payment_hash"]) + + created_at = wait["created_at"] + amount_sent = wait["amount_sent_msat"] + amount = wait["amount_msat"] + return PaymentResult( + destination=route.route[-1]["id"], payment_hash=pay["payment_hash"], payment_preimage=wait["payment_preimage"], - fee_msat=wait["amount_sent_msat"] - wait["amount_msat"], - time=wait["completed_at"] - wait["created_at"], + status=STATUS_COMPLETE, + amount_msat=Millisatoshi(amount), + amount_sent_msat=Millisatoshi(amount_sent), + fee_msat=Millisatoshi(amount_sent - amount), + parts=1, + created_at=created_at, + time=wait["completed_at"] - created_at, ) except RpcError as e: raise PaymentError(e.error) from None diff --git a/tools/plugins/mpay/protos/mpay.proto b/tools/plugins/mpay/protos/mpay.proto index b8d55d32..beb43242 100644 --- a/tools/plugins/mpay/protos/mpay.proto +++ b/tools/plugins/mpay/protos/mpay.proto @@ -88,6 +88,12 @@ message PayResponse { string payment_preimage = 2; uint64 fee_msat = 3; uint64 time = 4; + string destination = 5; + uint64 amount_msat = 6; + uint64 amount_sent_msat = 7; + uint32 parts = 8; + string status = 9; + uint64 created_at = 10; } message ResetPathMemoryRequest {} diff --git a/tools/plugins/mpay/protos/mpay_pb2.py b/tools/plugins/mpay/protos/mpay_pb2.py index b73d8bca..faecb97a 100644 --- a/tools/plugins/mpay/protos/mpay_pb2.py +++ b/tools/plugins/mpay/protos/mpay_pb2.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- # Generated by the protocol buffer compiler. DO NOT EDIT! # source: mpay.proto -# Protobuf Python Version: 4.25.0 +# Protobuf Python Version: 4.25.1 """Generated protocol buffer code.""" from google.protobuf import descriptor as _descriptor from google.protobuf import descriptor_pool as _descriptor_pool @@ -14,7 +14,7 @@ -DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\nmpay.proto\x12\x04mpay\"\x10\n\x0eGetInfoRequest\"\"\n\x0fGetInfoResponse\x12\x0f\n\x07version\x18\x01 \x01(\t\"\x98\x01\n\x10GetRoutesRequest\x12\x18\n\x0b\x64\x65stination\x18\x01 \x01(\tH\x00\x88\x01\x01\x12\x18\n\x0bmin_success\x18\x02 \x01(\x02H\x01\x88\x01\x01\x12\x1c\n\x0fmin_success_ema\x18\x03 \x01(\x02H\x02\x88\x01\x01\x42\x0e\n\x0c_destinationB\x0e\n\x0c_min_successB\x12\n\x10_min_success_ema\"\xa0\x02\n\x11GetRoutesResponse\x12\x33\n\x06routes\x18\x01 \x03(\x0b\x32#.mpay.GetRoutesResponse.RoutesEntry\x1a\x86\x01\n\x06Routes\x12\x34\n\x06routes\x18\x02 \x03(\x0b\x32$.mpay.GetRoutesResponse.Routes.Route\x1a\x46\n\x05Route\x12\r\n\x05route\x18\x01 \x03(\t\x12\x14\n\x0csuccess_rate\x18\x02 \x01(\x01\x12\x18\n\x10success_rate_ema\x18\x03 \x01(\x01\x1aM\n\x0bRoutesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12-\n\x05value\x18\x02 \x01(\x0b\x32\x1e.mpay.GetRoutesResponse.Routes:\x02\x38\x01\"M\n\x13ListPaymentsRequest\x12\x10\n\x06\x62olt11\x18\x01 \x01(\tH\x00\x12\x16\n\x0cpayment_hash\x18\x02 \x01(\tH\x00\x42\x0c\n\nidentifier\"\xd2\x03\n\x14ListPaymentsResponse\x12\x34\n\x08payments\x18\x01 \x03(\x0b\x32\".mpay.ListPaymentsResponse.Payment\x1a\x83\x03\n\x07Payment\x12\n\n\x02id\x18\x01 \x01(\x04\x12\x13\n\x0b\x64\x65stination\x18\x02 \x01(\t\x12\x14\n\x0cpayment_hash\x18\x03 \x01(\t\x12\x0e\n\x06\x61mount\x18\x04 \x01(\x04\x12\n\n\x02ok\x18\x05 \x01(\x08\x12<\n\x08\x61ttempts\x18\x06 \x03(\x0b\x32*.mpay.ListPaymentsResponse.Payment.Attempt\x12\x12\n\ncreated_at\x18\x07 \x01(\x04\x1a\xd2\x01\n\x07\x41ttempt\x12\n\n\x02id\x18\x01 \x01(\x04\x12\n\n\x02ok\x18\x02 \x01(\x08\x12\x0c\n\x04time\x18\x03 \x01(\x04\x12<\n\x04hops\x18\x04 \x03(\x0b\x32..mpay.ListPaymentsResponse.Payment.Attempt.Hop\x12\x12\n\ncreated_at\x18\x05 \x01(\x04\x1aO\n\x03Hop\x12\n\n\x02id\x18\x01 \x01(\x04\x12\x0c\n\x04node\x18\x02 \x01(\t\x12\x0f\n\x07\x63hannel\x18\x03 \x01(\t\x12\x11\n\tdirection\x18\x04 \x01(\x04\x12\n\n\x02ok\x18\x05 \x01(\x08\"\xc2\x01\n\nPayRequest\x12\x0e\n\x06\x62olt11\x18\x01 \x01(\t\x12\x19\n\x0cmax_fee_msat\x18\x02 \x01(\x04H\x00\x88\x01\x01\x12\x1c\n\x0f\x65xempt_fee_msat\x18\x03 \x01(\x04H\x01\x88\x01\x01\x12\x14\n\x07timeout\x18\x04 \x01(\x04H\x02\x88\x01\x01\x12\x16\n\tmax_delay\x18\x05 \x01(\x04H\x03\x88\x01\x01\x42\x0f\n\r_max_fee_msatB\x12\n\x10_exempt_fee_msatB\n\n\x08_timeoutB\x0c\n\n_max_delay\"]\n\x0bPayResponse\x12\x14\n\x0cpayment_hash\x18\x01 \x01(\t\x12\x18\n\x10payment_preimage\x18\x02 \x01(\t\x12\x10\n\x08\x66\x65\x65_msat\x18\x03 \x01(\x04\x12\x0c\n\x04time\x18\x04 \x01(\x04\"\x18\n\x16ResetPathMemoryRequest\"K\n\x17ResetPathMemoryResponse\x12\x10\n\x08payments\x18\x01 \x01(\x04\x12\x10\n\x08\x61ttempts\x18\x02 \x01(\x04\x12\x0c\n\x04hops\x18\x03 \x01(\x04\x32\xc9\x02\n\x04Mpay\x12\x38\n\x07GetInfo\x12\x14.mpay.GetInfoRequest\x1a\x15.mpay.GetInfoResponse\"\x00\x12>\n\tGetRoutes\x12\x16.mpay.GetRoutesRequest\x1a\x17.mpay.GetRoutesResponse\"\x00\x12G\n\x0cListPayments\x12\x19.mpay.ListPaymentsRequest\x1a\x1a.mpay.ListPaymentsResponse\"\x00\x12,\n\x03Pay\x12\x10.mpay.PayRequest\x1a\x11.mpay.PayResponse\"\x00\x12P\n\x0fResetPathMemory\x12\x1c.mpay.ResetPathMemoryRequest\x1a\x1d.mpay.ResetPathMemoryResponse\"\x00\x62\x06proto3') +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\nmpay.proto\x12\x04mpay\"\x10\n\x0eGetInfoRequest\"\"\n\x0fGetInfoResponse\x12\x0f\n\x07version\x18\x01 \x01(\t\"\x98\x01\n\x10GetRoutesRequest\x12\x18\n\x0b\x64\x65stination\x18\x01 \x01(\tH\x00\x88\x01\x01\x12\x18\n\x0bmin_success\x18\x02 \x01(\x02H\x01\x88\x01\x01\x12\x1c\n\x0fmin_success_ema\x18\x03 \x01(\x02H\x02\x88\x01\x01\x42\x0e\n\x0c_destinationB\x0e\n\x0c_min_successB\x12\n\x10_min_success_ema\"\xa0\x02\n\x11GetRoutesResponse\x12\x33\n\x06routes\x18\x01 \x03(\x0b\x32#.mpay.GetRoutesResponse.RoutesEntry\x1a\x86\x01\n\x06Routes\x12\x34\n\x06routes\x18\x02 \x03(\x0b\x32$.mpay.GetRoutesResponse.Routes.Route\x1a\x46\n\x05Route\x12\r\n\x05route\x18\x01 \x03(\t\x12\x14\n\x0csuccess_rate\x18\x02 \x01(\x01\x12\x18\n\x10success_rate_ema\x18\x03 \x01(\x01\x1aM\n\x0bRoutesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12-\n\x05value\x18\x02 \x01(\x0b\x32\x1e.mpay.GetRoutesResponse.Routes:\x02\x38\x01\"M\n\x13ListPaymentsRequest\x12\x10\n\x06\x62olt11\x18\x01 \x01(\tH\x00\x12\x16\n\x0cpayment_hash\x18\x02 \x01(\tH\x00\x42\x0c\n\nidentifier\"\xd2\x03\n\x14ListPaymentsResponse\x12\x34\n\x08payments\x18\x01 \x03(\x0b\x32\".mpay.ListPaymentsResponse.Payment\x1a\x83\x03\n\x07Payment\x12\n\n\x02id\x18\x01 \x01(\x04\x12\x13\n\x0b\x64\x65stination\x18\x02 \x01(\t\x12\x14\n\x0cpayment_hash\x18\x03 \x01(\t\x12\x0e\n\x06\x61mount\x18\x04 \x01(\x04\x12\n\n\x02ok\x18\x05 \x01(\x08\x12<\n\x08\x61ttempts\x18\x06 \x03(\x0b\x32*.mpay.ListPaymentsResponse.Payment.Attempt\x12\x12\n\ncreated_at\x18\x07 \x01(\x04\x1a\xd2\x01\n\x07\x41ttempt\x12\n\n\x02id\x18\x01 \x01(\x04\x12\n\n\x02ok\x18\x02 \x01(\x08\x12\x0c\n\x04time\x18\x03 \x01(\x04\x12<\n\x04hops\x18\x04 \x03(\x0b\x32..mpay.ListPaymentsResponse.Payment.Attempt.Hop\x12\x12\n\ncreated_at\x18\x05 \x01(\x04\x1aO\n\x03Hop\x12\n\n\x02id\x18\x01 \x01(\x04\x12\x0c\n\x04node\x18\x02 \x01(\t\x12\x0f\n\x07\x63hannel\x18\x03 \x01(\t\x12\x11\n\tdirection\x18\x04 \x01(\x04\x12\n\n\x02ok\x18\x05 \x01(\x08\"\xc2\x01\n\nPayRequest\x12\x0e\n\x06\x62olt11\x18\x01 \x01(\t\x12\x19\n\x0cmax_fee_msat\x18\x02 \x01(\x04H\x00\x88\x01\x01\x12\x1c\n\x0f\x65xempt_fee_msat\x18\x03 \x01(\x04H\x01\x88\x01\x01\x12\x14\n\x07timeout\x18\x04 \x01(\x04H\x02\x88\x01\x01\x12\x16\n\tmax_delay\x18\x05 \x01(\x04H\x03\x88\x01\x01\x42\x0f\n\r_max_fee_msatB\x12\n\x10_exempt_fee_msatB\n\n\x08_timeoutB\x0c\n\n_max_delay\"\xd4\x01\n\x0bPayResponse\x12\x14\n\x0cpayment_hash\x18\x01 \x01(\t\x12\x18\n\x10payment_preimage\x18\x02 \x01(\t\x12\x10\n\x08\x66\x65\x65_msat\x18\x03 \x01(\x04\x12\x0c\n\x04time\x18\x04 \x01(\x04\x12\x13\n\x0b\x64\x65stination\x18\x05 \x01(\t\x12\x13\n\x0b\x61mount_msat\x18\x06 \x01(\x04\x12\x18\n\x10\x61mount_sent_msat\x18\x07 \x01(\x04\x12\r\n\x05parts\x18\x08 \x01(\r\x12\x0e\n\x06status\x18\t \x01(\t\x12\x12\n\ncreated_at\x18\n \x01(\x04\"\x18\n\x16ResetPathMemoryRequest\"K\n\x17ResetPathMemoryResponse\x12\x10\n\x08payments\x18\x01 \x01(\x04\x12\x10\n\x08\x61ttempts\x18\x02 \x01(\x04\x12\x0c\n\x04hops\x18\x03 \x01(\x04\x32\xc9\x02\n\x04Mpay\x12\x38\n\x07GetInfo\x12\x14.mpay.GetInfoRequest\x1a\x15.mpay.GetInfoResponse\"\x00\x12>\n\tGetRoutes\x12\x16.mpay.GetRoutesRequest\x1a\x17.mpay.GetRoutesResponse\"\x00\x12G\n\x0cListPayments\x12\x19.mpay.ListPaymentsRequest\x1a\x1a.mpay.ListPaymentsResponse\"\x00\x12,\n\x03Pay\x12\x10.mpay.PayRequest\x1a\x11.mpay.PayResponse\"\x00\x12P\n\x0fResetPathMemory\x12\x1c.mpay.ResetPathMemoryRequest\x1a\x1d.mpay.ResetPathMemoryResponse\"\x00\x62\x06proto3') _globals = globals() _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) @@ -49,12 +49,12 @@ _globals['_LISTPAYMENTSRESPONSE_PAYMENT_ATTEMPT_HOP']._serialized_end=1066 _globals['_PAYREQUEST']._serialized_start=1069 _globals['_PAYREQUEST']._serialized_end=1263 - _globals['_PAYRESPONSE']._serialized_start=1265 - _globals['_PAYRESPONSE']._serialized_end=1358 - _globals['_RESETPATHMEMORYREQUEST']._serialized_start=1360 - _globals['_RESETPATHMEMORYREQUEST']._serialized_end=1384 - _globals['_RESETPATHMEMORYRESPONSE']._serialized_start=1386 - _globals['_RESETPATHMEMORYRESPONSE']._serialized_end=1461 - _globals['_MPAY']._serialized_start=1464 - _globals['_MPAY']._serialized_end=1793 + _globals['_PAYRESPONSE']._serialized_start=1266 + _globals['_PAYRESPONSE']._serialized_end=1478 + _globals['_RESETPATHMEMORYREQUEST']._serialized_start=1480 + _globals['_RESETPATHMEMORYREQUEST']._serialized_end=1504 + _globals['_RESETPATHMEMORYRESPONSE']._serialized_start=1506 + _globals['_RESETPATHMEMORYRESPONSE']._serialized_end=1581 + _globals['_MPAY']._serialized_start=1584 + _globals['_MPAY']._serialized_end=1913 # @@protoc_insertion_point(module_scope) diff --git a/tools/plugins/mpay/protos/mpay_pb2.pyi b/tools/plugins/mpay/protos/mpay_pb2.pyi index d97f8a2a..57b74728 100644 --- a/tools/plugins/mpay/protos/mpay_pb2.pyi +++ b/tools/plugins/mpay/protos/mpay_pb2.pyi @@ -124,16 +124,28 @@ class PayRequest(_message.Message): def __init__(self, bolt11: _Optional[str] = ..., max_fee_msat: _Optional[int] = ..., exempt_fee_msat: _Optional[int] = ..., timeout: _Optional[int] = ..., max_delay: _Optional[int] = ...) -> None: ... class PayResponse(_message.Message): - __slots__ = ("payment_hash", "payment_preimage", "fee_msat", "time") + __slots__ = ("payment_hash", "payment_preimage", "fee_msat", "time", "destination", "amount_msat", "amount_sent_msat", "parts", "status", "created_at") PAYMENT_HASH_FIELD_NUMBER: _ClassVar[int] PAYMENT_PREIMAGE_FIELD_NUMBER: _ClassVar[int] FEE_MSAT_FIELD_NUMBER: _ClassVar[int] TIME_FIELD_NUMBER: _ClassVar[int] + DESTINATION_FIELD_NUMBER: _ClassVar[int] + AMOUNT_MSAT_FIELD_NUMBER: _ClassVar[int] + AMOUNT_SENT_MSAT_FIELD_NUMBER: _ClassVar[int] + PARTS_FIELD_NUMBER: _ClassVar[int] + STATUS_FIELD_NUMBER: _ClassVar[int] + CREATED_AT_FIELD_NUMBER: _ClassVar[int] payment_hash: str payment_preimage: str fee_msat: int time: int - def __init__(self, payment_hash: _Optional[str] = ..., payment_preimage: _Optional[str] = ..., fee_msat: _Optional[int] = ..., time: _Optional[int] = ...) -> None: ... + destination: str + amount_msat: int + amount_sent_msat: int + parts: int + status: str + created_at: int + def __init__(self, payment_hash: _Optional[str] = ..., payment_preimage: _Optional[str] = ..., fee_msat: _Optional[int] = ..., time: _Optional[int] = ..., destination: _Optional[str] = ..., amount_msat: _Optional[int] = ..., amount_sent_msat: _Optional[int] = ..., parts: _Optional[int] = ..., status: _Optional[str] = ..., created_at: _Optional[int] = ...) -> None: ... class ResetPathMemoryRequest(_message.Message): __slots__ = () diff --git a/tools/plugins/mpay/rpc/server.py b/tools/plugins/mpay/rpc/server.py index d24ca387..76832dbf 100644 --- a/tools/plugins/mpay/rpc/server.py +++ b/tools/plugins/mpay/rpc/server.py @@ -56,10 +56,16 @@ def Pay(self, request: PayRequest, context: grpc.ServicerContext) -> PayResponse ) return PayResponse( + destination=res.destination, payment_hash=res.payment_hash, payment_preimage=res.payment_preimage, + amount_msat=int(res.amount_msat), + amount_sent_msat=int(res.amount_sent_msat), fee_msat=int(res.fee_msat), + parts=res.parts, + status=res.status, time=res.time, + created_at=res.created_at, ) def GetRoutes( # noqa: N802 diff --git a/tools/plugins/mpay/rpc/tests/test_server.py b/tools/plugins/mpay/rpc/tests/test_server.py index ec4aae84..fe8bc4d9 100644 --- a/tools/plugins/mpay/rpc/tests/test_server.py +++ b/tools/plugins/mpay/rpc/tests/test_server.py @@ -19,6 +19,7 @@ ) from plugins.mpay.config import OptionDefaults from plugins.mpay.consts import VERSION +from plugins.mpay.pay.sendpay import STATUS_COMPLETE from plugins.mpay.protos.mpay_pb2 import ( GetInfoRequest, GetInfoResponse, @@ -69,15 +70,30 @@ def test_get_info(self, cl: MpayStub) -> None: @pytest.mark.parametrize("node", [LndNode.One, LndNode.Two]) def test_pay(self, cl: MpayStub, node: LndNode) -> None: invoice = lnd(node, "addinvoice 1")["payment_request"] - dec = bolt11.decode(invoice) + self.invoice = invoice res: PayResponse = cl.Pay(PayRequest(bolt11=invoice)) + dec = bolt11.decode(invoice) + + assert res.destination == dec.payee assert res.payment_hash == dec.payment_hash assert hashlib.sha256(bytes.fromhex(res.payment_preimage)).hexdigest() == dec.payment_hash + assert res.amount_msat == 1_000 + assert res.amount_sent_msat == 1_000 + assert res.parts == 1 + assert res.status == STATUS_COMPLETE assert res.time < 10 assert res.fee_msat == 0 + def test_pay_twice(self, cl: MpayStub) -> None: + invoice = lnd(LndNode.One, "listinvoices")["invoices"][-1] + res: PayResponse = cl.Pay(PayRequest(bolt11=invoice["payment_request"])) + + assert res.time == 0 + assert res.payment_hash == invoice["r_hash"] + assert res.payment_preimage == invoice["r_preimage"] + @pytest.mark.parametrize(("min_success", "min_success_ema"), [(2, 0), (0, 2)]) def test_get_routes_min_success( self, cl: MpayStub, min_success: int, min_success_ema: int