Skip to content

Commit

Permalink
Add endpoint for decoding invoices via gRPC
Browse files Browse the repository at this point in the history
  • Loading branch information
w3irdrobot committed May 5, 2022
1 parent b29c215 commit f957aaa
Show file tree
Hide file tree
Showing 5 changed files with 176 additions and 25 deletions.
42 changes: 41 additions & 1 deletion proto/sensei.proto
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ service Node {
rpc GetBalance (GetBalanceRequest) returns (GetBalanceResponse);
rpc OpenChannel (OpenChannelRequest) returns (OpenChannelResponse);
rpc PayInvoice (PayInvoiceRequest) returns (PayInvoiceResponse);
rpc DecodeInvoice (DecodeInvoiceRequest) returns (DecodeInvoiceResponse);
rpc Keysend (KeysendRequest) returns (KeysendResponse);
rpc CreateInvoice (CreateInvoiceRequest) returns (CreateInvoiceResponse);
rpc LabelPayment (LabelPaymentRequest) returns (LabelPaymentResponse);
Expand Down Expand Up @@ -197,6 +198,45 @@ message PayInvoiceRequest {
}
message PayInvoiceResponse {}

message DecodeInvoiceRequest {
string invoice = 1;
}
message DecodeInvoiceResponse {
Invoice invoice = 1;
}
message Invoice {
string payment_hash = 1;
string currency = 2;
uint64 amount = 3;
string description = 4;
uint64 expiry = 5;
uint64 timestamp = 6;
uint64 min_final_cltv_expiry = 7;
repeated RouteHint route_hints = 8;
Features features = 9;
string payee_pub_key = 10;
}
message RouteHint {
repeated RouteHintHop hops = 1;
}
message RouteHintHop {
string src_node_id = 1;
uint64 short_channel_id = 2;
RoutingFees fees = 3;
uint32 cltv_expiry_delta = 4;
optional uint64 htlc_minimum_msat = 5;
optional uint64 htlc_maximum_msat = 6;
}
message RoutingFees {
uint32 base_msat = 1;
uint32 proportional_millionths = 2;
}
message Features {
bool variable_length_onion = 1;
bool payment_secret = 2;
bool basic_mpp = 3;
}

message LabelPaymentRequest {
string label = 1;
string payment_hash = 2;
Expand Down Expand Up @@ -325,4 +365,4 @@ message VerifyMessageRequest {
message VerifyMessageResponse {
bool valid = 1;
string pubkey = 2;
}
}
34 changes: 28 additions & 6 deletions src/grpc/adaptor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,13 @@ use super::sensei::{

use super::sensei::{
CloseChannelRequest, CloseChannelResponse, ConnectPeerRequest, ConnectPeerResponse,
CreateInvoiceRequest, CreateInvoiceResponse, GetBalanceRequest, GetBalanceResponse,
GetUnusedAddressRequest, GetUnusedAddressResponse, InfoRequest, InfoResponse, KeysendRequest,
KeysendResponse, ListChannelsRequest, ListChannelsResponse, ListPaymentsRequest,
ListPaymentsResponse, ListPeersRequest, ListPeersResponse, OpenChannelRequest,
OpenChannelResponse, PayInvoiceRequest, PayInvoiceResponse, SignMessageRequest,
SignMessageResponse, VerifyMessageRequest, VerifyMessageResponse,
CreateInvoiceRequest, CreateInvoiceResponse, DecodeInvoiceRequest, DecodeInvoiceResponse,
GetBalanceRequest, GetBalanceResponse, GetUnusedAddressRequest, GetUnusedAddressResponse,
InfoRequest, InfoResponse, KeysendRequest, KeysendResponse, ListChannelsRequest,
ListChannelsResponse, ListPaymentsRequest, ListPaymentsResponse, ListPeersRequest,
ListPeersResponse, OpenChannelRequest, OpenChannelResponse, PayInvoiceRequest,
PayInvoiceResponse, SignMessageRequest, SignMessageResponse, VerifyMessageRequest,
VerifyMessageResponse,
};

use crate::services::{
Expand Down Expand Up @@ -234,6 +235,27 @@ impl TryFrom<NodeResponse> for PayInvoiceResponse {
}
}

impl From<DecodeInvoiceRequest> for NodeRequest {
fn from(req: DecodeInvoiceRequest) -> Self {
NodeRequest::DecodeInvoice {
invoice: req.invoice,
}
}
}

impl TryFrom<NodeResponse> for DecodeInvoiceResponse {
type Error = String;

fn try_from(res: NodeResponse) -> Result<Self, Self::Error> {
match res {
NodeResponse::DecodeInvoice { invoice } => Ok(Self {
invoice: Some(invoice.into()),
}),
_ => Err("impossible".to_string()),
}
}
}

impl From<KeysendRequest> for NodeRequest {
fn from(req: KeysendRequest) -> Self {
NodeRequest::Keysend {
Expand Down
69 changes: 69 additions & 0 deletions src/grpc/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,74 @@ pub mod node;
pub mod utils;

pub mod sensei {
use crate::node::{
LocalInvoice, LocalInvoiceFeatures, LocalRouteHint, LocalRouteHintHop, LocalRoutingFees,
};

tonic::include_proto!("sensei");

impl From<LocalInvoice> for Invoice {
fn from(invoice: LocalInvoice) -> Self {
Invoice {
payment_hash: invoice.payment_hash,
currency: invoice.currency,
amount: invoice.amount,
description: invoice.description,
expiry: invoice.expiry,
timestamp: invoice.timestamp,
min_final_cltv_expiry: invoice.min_final_cltv_expiry,
route_hints: invoice
.route_hints
.into_iter()
.map(|h| LocalRouteHint::from(&h).into())
.collect(),
features: invoice.features.map(|f| f.into()),
payee_pub_key: invoice.payee_pub_key.to_string(),
}
}
}

impl From<LocalRouteHint> for RouteHint {
fn from(hint: LocalRouteHint) -> Self {
Self {
hops: hint
.hops
.into_iter()
.map(|h| LocalRouteHintHop::from(&h).into())
.collect(),
}
}
}

impl From<LocalRouteHintHop> for RouteHintHop {
fn from(hop: LocalRouteHintHop) -> Self {
Self {
src_node_id: hop.src_node_id.to_string(),
short_channel_id: hop.short_channel_id,
fees: Some(LocalRoutingFees::from(hop.fees).into()),
cltv_expiry_delta: hop.cltv_expiry_delta.into(),
htlc_minimum_msat: hop.htlc_minimum_msat,
htlc_maximum_msat: hop.htlc_maximum_msat,
}
}
}

impl From<LocalRoutingFees> for RoutingFees {
fn from(fees: LocalRoutingFees) -> Self {
Self {
base_msat: fees.base_msat,
proportional_millionths: fees.proportional_millionths,
}
}
}

impl From<LocalInvoiceFeatures> for Features {
fn from(features: LocalInvoiceFeatures) -> Self {
Self {
variable_length_onion: features.variable_length_onion,
payment_secret: features.payment_secret,
basic_mpp: features.basic_mpp,
}
}
}
}
27 changes: 19 additions & 8 deletions src/grpc/node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,15 @@ pub use super::sensei::node_server::{Node, NodeServer};
use super::{
sensei::{
CloseChannelRequest, CloseChannelResponse, ConnectPeerRequest, ConnectPeerResponse,
CreateInvoiceRequest, CreateInvoiceResponse, DeletePaymentRequest, DeletePaymentResponse,
GetBalanceRequest, GetBalanceResponse, GetUnusedAddressRequest, GetUnusedAddressResponse,
InfoRequest, InfoResponse, KeysendRequest, KeysendResponse, LabelPaymentRequest,
LabelPaymentResponse, ListChannelsRequest, ListChannelsResponse, ListPaymentsRequest,
ListPaymentsResponse, ListPeersRequest, ListPeersResponse, OpenChannelRequest,
OpenChannelResponse, PayInvoiceRequest, PayInvoiceResponse, SignMessageRequest,
SignMessageResponse, StartNodeRequest, StartNodeResponse, StopNodeRequest,
StopNodeResponse, VerifyMessageRequest, VerifyMessageResponse,
CreateInvoiceRequest, CreateInvoiceResponse, DecodeInvoiceRequest, DecodeInvoiceResponse,
DeletePaymentRequest, DeletePaymentResponse, GetBalanceRequest, GetBalanceResponse,
GetUnusedAddressRequest, GetUnusedAddressResponse, InfoRequest, InfoResponse,
KeysendRequest, KeysendResponse, LabelPaymentRequest, LabelPaymentResponse,
ListChannelsRequest, ListChannelsResponse, ListPaymentsRequest, ListPaymentsResponse,
ListPeersRequest, ListPeersResponse, OpenChannelRequest, OpenChannelResponse,
PayInvoiceRequest, PayInvoiceResponse, SignMessageRequest, SignMessageResponse,
StartNodeRequest, StartNodeResponse, StopNodeRequest, StopNodeResponse,
VerifyMessageRequest, VerifyMessageResponse,
},
utils::raw_macaroon_from_metadata,
};
Expand Down Expand Up @@ -170,6 +171,16 @@ impl Node for NodeService {
.map(Response::new)
.map_err(|_e| Status::unknown("unknown error"))
}
async fn decode_invoice(
&self,
request: tonic::Request<DecodeInvoiceRequest>,
) -> Result<tonic::Response<DecodeInvoiceResponse>, tonic::Status> {
self.authenticated_request(request.metadata().clone(), request.into_inner().into())
.await?
.try_into()
.map(Response::new)
.map_err(|_e| Status::unknown("unknown error"))
}
async fn keysend(
&self,
request: tonic::Request<KeysendRequest>,
Expand Down
29 changes: 19 additions & 10 deletions src/node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,17 +77,17 @@ use tokio::task::JoinHandle;

#[derive(Serialize, Debug)]
pub struct LocalInvoice {
payment_hash: String,
currency: String,
amount: u64,
description: String,
expiry: u64,
timestamp: u64,
min_final_cltv_expiry: u64,
pub payment_hash: String,
pub currency: String,
pub amount: u64,
pub description: String,
pub expiry: u64,
pub timestamp: u64,
pub min_final_cltv_expiry: u64,
#[serde(serialize_with = "serialize_route_hints")]
route_hints: Vec<RouteHint>,
features: Option<LocalInvoiceFeatures>,
payee_pub_key: PublicKey,
pub route_hints: Vec<RouteHint>,
pub features: Option<LocalInvoiceFeatures>,
pub payee_pub_key: PublicKey,
}

fn serialize_route_hints<S>(vector: &Vec<RouteHint>, serializer: S) -> Result<S::Ok, S::Error>
Expand Down Expand Up @@ -186,6 +186,15 @@ pub struct LocalRoutingFees {
pub proportional_millionths: u32,
}

impl From<RoutingFees> for LocalRoutingFees {
fn from(fees: RoutingFees) -> Self {
Self {
base_msat: fees.base_msat,
proportional_millionths: fees.proportional_millionths,
}
}
}

#[derive(Serialize, Debug)]
pub struct LocalInvoiceFeatures {
pub variable_length_onion: bool,
Expand Down

0 comments on commit f957aaa

Please sign in to comment.