msggen: Add notification-structs to cln_rpc

In Core Lightning notifications are JSON-messages. This commit
introduces structs that can be used to parse the notification
messages.

Using `msggen` all required tructs are automatically generated
This commit is contained in:
Erik De Smedt 2024-02-07 15:04:07 +01:00 committed by Christian Decker
parent 0251b45027
commit 15276b7ff5
4 changed files with 148 additions and 4 deletions

View file

@ -1,4 +1,94 @@
use serde::{Deserialize, Serialize}; // This file is autogenerated by `msggen`
// Do not edit it manually, your changes will be overwritten
use crate::primitives::*;
use serde::{Serialize, Deserialize};
#[derive(Clone, Debug, Deserialize, Serialize)]
pub enum Notification {
#[serde(rename = "block_added")]
BlockAdded(BlockAddedNotification),
#[serde(rename = "channel_open_failed")]
ChannelOpenFailed(ChannelOpenFailedNotification),
#[serde(rename = "channel_opened")]
ChannelOpened(ChannelOpenedNotification),
#[serde(rename = "connect")]
Connect(ConnectNotification),
#[serde(rename = "custommsg")]
CustomMsg(CustomMsgNotification),
}
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct BlockAddedNotification {
#[serde(skip_serializing_if = "Option::is_none")]
pub hash: Option<Sha256>,
#[serde(skip_serializing_if = "Option::is_none")]
pub height: Option<u32>,
}
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct ChannelOpenFailedNotification {
#[serde(skip_serializing_if = "Option::is_none")]
pub channel_id: Option<Sha256>,
}
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct ChannelOpenedNotification {
#[serde(skip_serializing_if = "Option::is_none")]
pub channel_ready: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
pub funding_msat: Option<Amount>,
#[serde(skip_serializing_if = "Option::is_none")]
pub funding_txid: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub id: Option<PublicKey>,
}
#[derive(Copy, Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
pub enum ConnectDirection {
#[serde(rename = "in")]
IN = 0,
#[serde(rename = "out")]
OUT = 1,
}
impl TryFrom<i32> for ConnectDirection {
type Error = anyhow::Error;
fn try_from(c: i32) -> Result<ConnectDirection, anyhow::Error> {
match c {
0 => Ok(ConnectDirection::IN),
1 => Ok(ConnectDirection::OUT),
o => Err(anyhow::anyhow!("Unknown variant {} for enum ConnectDirection", o)),
}
}
}
impl ToString for ConnectDirection {
fn to_string(&self) -> String {
match self {
ConnectDirection::IN => "IN",
ConnectDirection::OUT => "OUT",
}.to_string()
}
}
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct ConnectNotification {
#[serde(skip_serializing_if = "Option::is_none")]
pub address: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub direction: Option<ConnectDirection>,
#[serde(skip_serializing_if = "Option::is_none")]
pub id: Option<PublicKey>,
}
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct CustomMsgNotification {
#[serde(skip_serializing_if = "Option::is_none")]
pub payload: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub peer_id: Option<PublicKey>,
}
#[derive(Debug, Deserialize, Serialize)]
pub enum Notification {}

View file

@ -4,7 +4,7 @@ import argparse
from pathlib import Path from pathlib import Path
from msggen.gen.grpc import GrpcGenerator, GrpcConverterGenerator, GrpcUnconverterGenerator, GrpcServerGenerator from msggen.gen.grpc import GrpcGenerator, GrpcConverterGenerator, GrpcUnconverterGenerator, GrpcServerGenerator
from msggen.gen.grpc2py import Grpc2PyGenerator from msggen.gen.grpc2py import Grpc2PyGenerator
from msggen.gen.rpc.rust import RustGenerator from msggen.gen.rpc import RustGenerator, NotificationGenerator
from msggen.gen.generator import GeneratorChain from msggen.gen.generator import GeneratorChain
from msggen.utils import load_jsonrpc_service, combine_schemas from msggen.utils import load_jsonrpc_service, combine_schemas
import logging import logging
@ -49,6 +49,10 @@ def add_handler_gen_rust_jsonrpc(generator_chain: GeneratorChain, meta):
dest = open(fname, "w") dest = open(fname, "w")
generator_chain.add_generator(RustGenerator(dest, meta)) generator_chain.add_generator(RustGenerator(dest, meta))
fname = Path("cln-rpc") / "src" / "notifications.rs"
dest = open(fname, "w")
generator_chain.add_generator(NotificationGenerator(dest, meta))
def load_msggen_meta(): def load_msggen_meta():
meta = json.load(open('.msggen.json', 'r')) meta = json.load(open('.msggen.json', 'r'))

View file

@ -0,0 +1,4 @@
from msggen.gen.rpc.notification import NotificationGenerator
from msggen.gen.rpc.rust import RustGenerator
__all__ = [RustGenerator, NotificationGenerator]

View file

@ -0,0 +1,46 @@
import logging
from textwrap import dedent, indent
from typing import Any, Dict, Optional, TextIO
from msggen.model import Service
from msggen.gen.generator import IGenerator
from msggen.gen.rpc.rust import gen_composite
class NotificationGenerator(IGenerator):
def __init__(self, dest: TextIO, meta: Dict[str, Any]):
self.dest = dest
self.logger = logging.getLogger(__name__)
self.meta = meta
def write(self, text: str, numindent: Optional[int] = None) -> None:
raw = dedent(text)
if numindent is not None:
raw = indent(text, " " * numindent)
self.dest.write(raw)
def generate_enum(self, service: Service):
self.write("#[derive(Clone, Debug, Deserialize, Serialize)]\n")
self.write("pub enum Notification {\n")
for notification in service.notifications:
tn = notification.typename
name = notification.name
self.write(f'#[serde(rename = "{name}")]\n', numindent=1)
self.write(f"{tn}({tn}Notification),\n", numindent=1),
self.write("}\n")
def generate(self, service: Service) -> None:
self.write("// This file is autogenerated by `msggen`\n")
self.write("// Do not edit it manually, your changes will be overwritten\n\n\n")
self.write("\n")
self.write("use crate::primitives::*;\n")
self.write("use serde::{Serialize, Deserialize};\n")
self.generate_enum(service)
self.write("\n\n")
for notification in service.notifications:
_, resp_decl = gen_composite(notification.response, self.meta)
self.write(resp_decl)