msggen: Add FetchInvoice method to Rust and grpc bindings

Closes #6844

Changelog-Added: Cln-RPC: Add `fetchinvoice` method to cln-rpc and cln-grpc.
This commit is contained in:
Christian Decker
2023-11-07 13:42:24 +01:00
committed by Peter Neuroth
parent 9e0b244058
commit bdfd2d5fda
8 changed files with 394 additions and 1 deletions

View File

@@ -697,6 +697,35 @@
"Feerates.perkw": 3,
"Feerates.warning_missing_feerates": 1
},
"FetchinvoiceChanges": {
"FetchInvoice.changes.amount_msat": 5,
"FetchInvoice.changes.description": 2,
"FetchInvoice.changes.description_appended": 1,
"FetchInvoice.changes.vendor": 4,
"FetchInvoice.changes.vendor_removed": 3
},
"FetchinvoiceNext_period": {
"FetchInvoice.next_period.counter": 1,
"FetchInvoice.next_period.endtime": 3,
"FetchInvoice.next_period.paywindow_end": 5,
"FetchInvoice.next_period.paywindow_start": 4,
"FetchInvoice.next_period.starttime": 2
},
"FetchinvoiceRequest": {
"FetchInvoice.amount_msat": 2,
"FetchInvoice.offer": 1,
"FetchInvoice.payer_note": 8,
"FetchInvoice.quantity": 3,
"FetchInvoice.recurrence_counter": 4,
"FetchInvoice.recurrence_label": 6,
"FetchInvoice.recurrence_start": 5,
"FetchInvoice.timeout": 7
},
"FetchinvoiceResponse": {
"FetchInvoice.changes": 2,
"FetchInvoice.invoice": 1,
"FetchInvoice.next_period": 3
},
"FundchannelRequest": {
"FundChannel.amount": 1,
"FundChannel.announce": 3,
@@ -2853,6 +2882,94 @@
"added": "pre-v0.10.1",
"deprecated": false
},
"FetchInvoice": {
"added": "pre-v0.10.1",
"deprecated": null
},
"FetchInvoice.amount_msat": {
"added": "pre-v0.10.1",
"deprecated": false
},
"FetchInvoice.changes": {
"added": "pre-v0.10.1",
"deprecated": false
},
"FetchInvoice.changes.amount_msat": {
"added": "pre-v0.10.1",
"deprecated": false
},
"FetchInvoice.changes.description": {
"added": "pre-v0.10.1",
"deprecated": false
},
"FetchInvoice.changes.description_appended": {
"added": "pre-v0.10.1",
"deprecated": false
},
"FetchInvoice.changes.vendor": {
"added": "pre-v0.10.1",
"deprecated": false
},
"FetchInvoice.changes.vendor_removed": {
"added": "pre-v0.10.1",
"deprecated": false
},
"FetchInvoice.invoice": {
"added": "pre-v0.10.1",
"deprecated": false
},
"FetchInvoice.next_period": {
"added": "pre-v0.10.1",
"deprecated": false
},
"FetchInvoice.next_period.counter": {
"added": "pre-v0.10.1",
"deprecated": false
},
"FetchInvoice.next_period.endtime": {
"added": "pre-v0.10.1",
"deprecated": false
},
"FetchInvoice.next_period.paywindow_end": {
"added": "pre-v0.10.1",
"deprecated": false
},
"FetchInvoice.next_period.paywindow_start": {
"added": "pre-v0.10.1",
"deprecated": false
},
"FetchInvoice.next_period.starttime": {
"added": "pre-v0.10.1",
"deprecated": false
},
"FetchInvoice.offer": {
"added": "pre-v0.10.1",
"deprecated": false
},
"FetchInvoice.payer_note": {
"added": "pre-v0.10.1",
"deprecated": false
},
"FetchInvoice.quantity": {
"added": "pre-v0.10.1",
"deprecated": false
},
"FetchInvoice.recurrence_counter": {
"added": "pre-v0.10.1",
"deprecated": false
},
"FetchInvoice.recurrence_label": {
"added": "pre-v0.10.1",
"deprecated": false
},
"FetchInvoice.recurrence_start": {
"added": "pre-v0.10.1",
"deprecated": false
},
"FetchInvoice.timeout": {
"added": "pre-v0.10.1",
"deprecated": false
},
"FundChannel": {
"added": "pre-v0.10.1",
"deprecated": null

View File

@@ -52,6 +52,7 @@ service Node {
rpc Decode(DecodeRequest) returns (DecodeResponse) {}
rpc Disconnect(DisconnectRequest) returns (DisconnectResponse) {}
rpc Feerates(FeeratesRequest) returns (FeeratesResponse) {}
rpc FetchInvoice(FetchinvoiceRequest) returns (FetchinvoiceResponse) {}
rpc FundChannel(FundchannelRequest) returns (FundchannelResponse) {}
rpc GetRoute(GetrouteRequest) returns (GetrouteResponse) {}
rpc ListForwards(ListforwardsRequest) returns (ListforwardsResponse) {}
@@ -1566,6 +1567,39 @@ message FeeratesOnchain_fee_estimates {
uint64 htlc_success_satoshis = 5;
}
message FetchinvoiceRequest {
string offer = 1;
optional Amount amount_msat = 2;
optional uint64 quantity = 3;
optional uint64 recurrence_counter = 4;
optional double recurrence_start = 5;
optional string recurrence_label = 6;
optional double timeout = 7;
optional string payer_note = 8;
}
message FetchinvoiceResponse {
string invoice = 1;
FetchinvoiceChanges changes = 2;
optional FetchinvoiceNext_period next_period = 3;
}
message FetchinvoiceChanges {
optional string description_appended = 1;
optional string description = 2;
optional string vendor_removed = 3;
optional string vendor = 4;
optional Amount amount_msat = 5;
}
message FetchinvoiceNext_period {
uint64 counter = 1;
uint64 starttime = 2;
uint64 endtime = 3;
uint64 paywindow_start = 4;
uint64 paywindow_end = 5;
}
message FundchannelRequest {
bytes id = 9;
AmountOrAll amount = 1;

View File

@@ -1482,6 +1482,43 @@ impl From<responses::FeeratesResponse> for pb::FeeratesResponse {
}
}
#[allow(unused_variables)]
impl From<responses::FetchinvoiceChanges> for pb::FetchinvoiceChanges {
fn from(c: responses::FetchinvoiceChanges) -> Self {
Self {
description_appended: c.description_appended, // Rule #2 for type string?
description: c.description, // Rule #2 for type string?
vendor_removed: c.vendor_removed, // Rule #2 for type string?
vendor: c.vendor, // Rule #2 for type string?
amount_msat: c.amount_msat.map(|f| f.into()), // Rule #2 for type msat?
}
}
}
#[allow(unused_variables)]
impl From<responses::FetchinvoiceNext_period> for pb::FetchinvoiceNextPeriod {
fn from(c: responses::FetchinvoiceNext_period) -> Self {
Self {
counter: c.counter, // Rule #2 for type u64
starttime: c.starttime, // Rule #2 for type u64
endtime: c.endtime, // Rule #2 for type u64
paywindow_start: c.paywindow_start, // Rule #2 for type u64
paywindow_end: c.paywindow_end, // Rule #2 for type u64
}
}
}
#[allow(unused_variables)]
impl From<responses::FetchinvoiceResponse> for pb::FetchinvoiceResponse {
fn from(c: responses::FetchinvoiceResponse) -> Self {
Self {
invoice: c.invoice, // Rule #2 for type string
changes: Some(c.changes.into()),
next_period: c.next_period.map(|v| v.into()),
}
}
}
#[allow(unused_variables)]
impl From<responses::FundchannelResponse> for pb::FundchannelResponse {
fn from(c: responses::FundchannelResponse) -> Self {
@@ -2270,6 +2307,22 @@ impl From<requests::FeeratesRequest> for pb::FeeratesRequest {
}
}
#[allow(unused_variables)]
impl From<requests::FetchinvoiceRequest> for pb::FetchinvoiceRequest {
fn from(c: requests::FetchinvoiceRequest) -> Self {
Self {
offer: c.offer, // Rule #2 for type string
amount_msat: c.amount_msat.map(|f| f.into()), // Rule #2 for type msat?
quantity: c.quantity, // Rule #2 for type u64?
recurrence_counter: c.recurrence_counter, // Rule #2 for type u64?
recurrence_start: c.recurrence_start, // Rule #2 for type number?
recurrence_label: c.recurrence_label, // Rule #2 for type string?
timeout: c.timeout, // Rule #2 for type number?
payer_note: c.payer_note, // Rule #2 for type string?
}
}
}
#[allow(unused_variables)]
impl From<requests::FundchannelRequest> for pb::FundchannelRequest {
fn from(c: requests::FundchannelRequest) -> Self {
@@ -2983,6 +3036,22 @@ impl From<pb::FeeratesRequest> for requests::FeeratesRequest {
}
}
#[allow(unused_variables)]
impl From<pb::FetchinvoiceRequest> for requests::FetchinvoiceRequest {
fn from(c: pb::FetchinvoiceRequest) -> Self {
Self {
offer: c.offer, // Rule #1 for type string
amount_msat: c.amount_msat.map(|a| a.into()), // Rule #1 for type msat?
quantity: c.quantity, // Rule #1 for type u64?
recurrence_counter: c.recurrence_counter, // Rule #1 for type u64?
recurrence_start: c.recurrence_start, // Rule #1 for type number?
recurrence_label: c.recurrence_label, // Rule #1 for type string?
timeout: c.timeout, // Rule #1 for type number?
payer_note: c.payer_note, // Rule #1 for type string?
}
}
}
#[allow(unused_variables)]
impl From<pb::FundchannelRequest> for requests::FundchannelRequest {
fn from(c: pb::FundchannelRequest) -> Self {

View File

@@ -1434,6 +1434,38 @@ async fn feerates(
}
async fn fetch_invoice(
&self,
request: tonic::Request<pb::FetchinvoiceRequest>,
) -> Result<tonic::Response<pb::FetchinvoiceResponse>, tonic::Status> {
let req = request.into_inner();
let req: requests::FetchinvoiceRequest = req.into();
debug!("Client asked for fetch_invoice");
trace!("fetch_invoice request: {:?}", req);
let mut rpc = ClnRpc::new(&self.rpc_path)
.await
.map_err(|e| Status::new(Code::Internal, e.to_string()))?;
let result = rpc.call(Request::FetchInvoice(req))
.await
.map_err(|e| Status::new(
Code::Unknown,
format!("Error calling method FetchInvoice: {:?}", e)))?;
match result {
Response::FetchInvoice(r) => {
trace!("fetch_invoice response: {:?}", r);
Ok(tonic::Response::new(r.into()))
},
r => Err(Status::new(
Code::Internal,
format!(
"Unexpected result {:?} to method call FetchInvoice",
r
)
)),
}
}
async fn fund_channel(
&self,
request: tonic::Request<pb::FundchannelRequest>,

73
cln-rpc/src/model.rs generated
View File

@@ -58,6 +58,7 @@ pub enum Request {
Decode(requests::DecodeRequest),
Disconnect(requests::DisconnectRequest),
Feerates(requests::FeeratesRequest),
FetchInvoice(requests::FetchinvoiceRequest),
FundChannel(requests::FundchannelRequest),
GetRoute(requests::GetrouteRequest),
ListForwards(requests::ListforwardsRequest),
@@ -123,6 +124,7 @@ pub enum Response {
Decode(responses::DecodeResponse),
Disconnect(responses::DisconnectResponse),
Feerates(responses::FeeratesResponse),
FetchInvoice(responses::FetchinvoiceResponse),
FundChannel(responses::FundchannelResponse),
GetRoute(responses::GetrouteResponse),
ListForwards(responses::ListforwardsResponse),
@@ -1280,6 +1282,35 @@ pub mod requests {
type Response = super::responses::FeeratesResponse;
}
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct FetchinvoiceRequest {
pub offer: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub amount_msat: Option<Amount>,
#[serde(skip_serializing_if = "Option::is_none")]
pub quantity: Option<u64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub recurrence_counter: Option<u64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub recurrence_start: Option<f64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub recurrence_label: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub timeout: Option<f64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub payer_note: Option<String>,
}
impl From<FetchinvoiceRequest> for Request {
fn from(r: FetchinvoiceRequest) -> Self {
Request::FetchInvoice(r)
}
}
impl IntoRequest for FetchinvoiceRequest {
type Response = super::responses::FetchinvoiceResponse;
}
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct FundchannelRequest {
pub id: PublicKey,
@@ -4666,6 +4697,48 @@ pub mod responses {
}
}
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct FetchinvoiceChanges {
#[serde(skip_serializing_if = "Option::is_none")]
pub description_appended: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub description: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub vendor_removed: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub vendor: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub amount_msat: Option<Amount>,
}
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct FetchinvoiceNext_period {
pub counter: u64,
pub starttime: u64,
pub endtime: u64,
pub paywindow_start: u64,
pub paywindow_end: u64,
}
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct FetchinvoiceResponse {
pub invoice: String,
pub changes: FetchinvoiceChanges,
#[serde(skip_serializing_if = "Option::is_none")]
pub next_period: Option<FetchinvoiceNext_period>,
}
impl TryFrom<Response> for FetchinvoiceResponse {
type Error = super::TryFromResponseError;
fn try_from(response: Response) -> Result<Self, Self::Error> {
match response {
Response::FetchInvoice(response) => Ok(response),
_ => Err(TryFromResponseError)
}
}
}
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct FundchannelResponse {
pub tx: String,

View File

@@ -73,7 +73,7 @@ def load_jsonrpc_service(schema_dir: str):
# "disableoffer",
"Disconnect",
"Feerates",
# "fetchinvoice",
"FetchInvoice",
# "fundchannel_cancel",
# "fundchannel_complete",
"FundChannel",

View File

@@ -1268,6 +1268,32 @@ def feerates2py(m):
})
def fetchinvoice_changes2py(m):
return remove_default({
"description_appended": m.description_appended, # PrimitiveField in generate_composite
"description": m.description, # PrimitiveField in generate_composite
"vendor_removed": m.vendor_removed, # PrimitiveField in generate_composite
"vendor": m.vendor, # PrimitiveField in generate_composite
"amount_msat": amount2msat(m.amount_msat), # PrimitiveField in generate_composite
})
def fetchinvoice_next_period2py(m):
return remove_default({
"counter": m.counter, # PrimitiveField in generate_composite
"starttime": m.starttime, # PrimitiveField in generate_composite
"endtime": m.endtime, # PrimitiveField in generate_composite
"paywindow_start": m.paywindow_start, # PrimitiveField in generate_composite
"paywindow_end": m.paywindow_end, # PrimitiveField in generate_composite
})
def fetchinvoice2py(m):
return remove_default({
"invoice": m.invoice, # PrimitiveField in generate_composite
})
def fundchannel2py(m):
return remove_default({
"tx": hexlify(m.tx), # PrimitiveField in generate_composite

View File

@@ -0,0 +1,42 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"required": [
"offer"
],
"additionalProperties": false,
"properties": {
"offer": {
"type": "string",
"description": ""
},
"amount_msat": {
"type": "msat",
"description": "amount_msat is required if the offer does not specify an amount at all, otherwise it is optional (but presumably if you set it to less than the offer, you will get an error from the issuer)."
},
"quantity": {
"type": "u64",
"description": "quantity is is required if the offer specifies quantity_max, otherwise it is not allowed."
},
"recurrence_counter": {
"type": "u64",
"description": "recurrence_counter is required if the offer specifies recurrence, otherwise it is not allowed. recurrence_counter should first be set to 0, and incremented for each successive invoice in a given series."
},
"recurrence_start": {
"type": "number",
"description": "recurrence_start is required if the offer specifies recurrence_base with start_any_period set, otherwise it is not allowed. It indicates what period number to start at."
},
"recurrence_label": {
"type": "string",
"description": "recurrence_label is required if recurrence_counter is set, and otherwise is not allowed. It must be the same as prior fetchinvoice calls for the same recurrence, as it is used to link them together."
},
"timeout": {
"type": "number",
"description": "timeout is an optional timeout; if we don't get a reply before this we fail (default, 60 seconds)."
},
"payer_note": {
"type": "string",
"description": "payer_note is an optional payer note to ask the issuer to include in the fetched invoice."
}
}
}