diff --git a/contrib/msggen/msggen/__main__.py b/contrib/msggen/msggen/__main__.py index 1bb345dac..e6257efcf 100644 --- a/contrib/msggen/msggen/__main__.py +++ b/contrib/msggen/msggen/__main__.py @@ -1,5 +1,6 @@ import json from msggen.gen.grpc import GrpcGenerator, GrpcConverterGenerator, GrpcUnconverterGenerator, GrpcServerGenerator +from msggen.gen.grpc2py import Grpc2PyGenerator from msggen.gen.rust import RustGenerator from msggen.gen.generator import GeneratorChain from msggen.utils import repo_root, load_jsonrpc_service @@ -22,6 +23,12 @@ def add_handler_gen_grpc(generator_chain: GeneratorChain, meta): generator_chain.add_generator(GrpcServerGenerator(dest)) +def add_handler_get_grpc2py(generator_chain: GeneratorChain): + fname = repo_root() / "contrib" / "pyln-testing" / "pyln" / "testing" / "grpc2py.py" + dest = open(fname, "w") + generator_chain.add_generator(Grpc2PyGenerator(dest)) + + def add_handler_gen_rust_jsonrpc(generator_chain: GeneratorChain): fname = repo_root() / "cln-rpc" / "src" / "model.rs" dest = open(fname, "w") @@ -45,6 +52,7 @@ def run(): add_handler_gen_grpc(generator_chain, meta) add_handler_gen_rust_jsonrpc(generator_chain) + add_handler_get_grpc2py(generator_chain) generator_chain.generate(service) diff --git a/contrib/msggen/msggen/gen/grpc2py.py b/contrib/msggen/msggen/gen/grpc2py.py new file mode 100644 index 000000000..e0fe5959e --- /dev/null +++ b/contrib/msggen/msggen/gen/grpc2py.py @@ -0,0 +1,154 @@ +"""Converts the GRPC messages back to parsed JSON dicts in python. + +This can be used to expose a local JSON-RPC socket but then talk to +the node over the GRPC interface. + +""" +from msggen.model import ArrayField, CompositeField, EnumField, PrimitiveField, Service +from msggen.gen import IGenerator +import logging +from textwrap import dedent +from typing import TextIO +import re + + +def decamelcase(c): + return re.sub(r'(? None: + if cleanup: + self.dest.write(dedent(text)) + else: + self.dest.write(text) + + def generate(self, service: Service) -> None: + self.write("""\ + # This file was automatically derived from the JSON-RPC schemas in + # `doc/schemas`. Do not edit this file manually as it would get + # overwritten. + + import json + + + def hexlify(b): + return b if b is None else b.hex() + + def amount2msat(a): + return a.msat + + def amount_or_all2msat(a): + breakpoint() + + + def remove_default(d): + # grpc is really not good at empty values, they get replaced with the type's default value... + return {k: v for k, v in d.items() if v is not None and v != ""} + """) + + self.generate_responses(service) + + def generate_enum(self, prefix, field: EnumField): + name = field.name.normalized() + prefix = f"{prefix}_{str(name).lower()}" + if field.path.endswith("[]"): + self.converters[field.path] = "str(i)" + else: + self.converters[field.path] = "str(m.{{name}})" + + def generate_composite(self, prefix, field: CompositeField): + name = field.name.normalized() + if prefix: + prefix = f"{prefix}_{str(name).lower()}" + else: + prefix = f"{str(name).lower()}" + + for f in field.fields: + if isinstance(f, CompositeField): + self.generate_composite(prefix, f) + + elif isinstance(f, ArrayField) and isinstance(f.itemtype, CompositeField): + self.generate_composite(prefix, f.itemtype) + + elif isinstance(f, ArrayField) and isinstance(f.itemtype, EnumField): + self.generate_enum(prefix, f.itemtype) + + converter_name = f"{prefix}2py" + self.write(f""" + + def {converter_name}(m): + return remove_default({{ + """) + + for f in field.fields: + name = f.normalized() + if isinstance(f, PrimitiveField): + typ = f.typename + + rhs = self.converters[typ].format(name=f.name) + + self.write(f' "{name}": {rhs}, # PrimitiveField in generate_composite\n', cleanup=False) + + elif isinstance(f, ArrayField) and isinstance(f.itemtype, PrimitiveField): + rhs = self.converters[f.itemtype.typename].format(name=name) + self.write(f' "{name}": [{rhs} for i in {rhs}], # ArrayField[primitive] in generate_composite\n', cleanup=False) + + elif isinstance(f, ArrayField): + rhs = self.converters[f.path] + + self.write(f' "{name}": [{rhs} for i in m.{name}], # ArrayField[composite] in generate_composite\n', cleanup=False) + + elif isinstance(f, CompositeField): + rhs = self.converters[f.path].format(name=f.name) + # self.write(f' "{name}": {rhs}, # CompositeField in generate_composite\n', cleanup=False) + + elif isinstance(f, EnumField): + name = f.name + self.write(f' "{name}": str(m.{f.name.normalized()}), # EnumField in generate_composite\n', cleanup=False) + + self.write(f" }})\n", cleanup=False) + + # Add ourselves to the converters so if we were generated as a + # dependency for a composite they can find us again. We have + # two variants: an array one where the items are going to be + # called "i" so we don't clobber and one-of where the field is + # "m.{name}" which will be filled by the caller. + if field.path.endswith("[]"): + self.converters[field.path] = f"{converter_name}(i)" + else: + self.converters[field.path] = f"{converter_name}(m.{{name}})" diff --git a/contrib/pyln-testing/pyln/testing/grpc2py.py b/contrib/pyln-testing/pyln/testing/grpc2py.py new file mode 100644 index 000000000..a0bb67b47 --- /dev/null +++ b/contrib/pyln-testing/pyln/testing/grpc2py.py @@ -0,0 +1,842 @@ +# This file was automatically derived from the JSON-RPC schemas in +# `doc/schemas`. Do not edit this file manually as it would get +# overwritten. + +import json + + +def hexlify(b): + return b if b is None else b.hex() + +def amount2msat(a): + return a.msat + +def amount_or_all2msat(a): + breakpoint() + + +def remove_default(d): + # grpc is really not good at empty values, they get replaced with the type's default value... + return {k: v for k, v in d.items() if v is not None and v != ""} + + +def getinfo_our_features2py(m): + return remove_default({ + "init": hexlify(m.init), # PrimitiveField in generate_composite + "node": hexlify(m.node), # PrimitiveField in generate_composite + "channel": hexlify(m.channel), # PrimitiveField in generate_composite + "invoice": hexlify(m.invoice), # PrimitiveField in generate_composite + }) + + +def getinfo_address2py(m): + return remove_default({ + "type": str(m.item_type), # EnumField in generate_composite + "port": m.port, # PrimitiveField in generate_composite + "address": m.address, # PrimitiveField in generate_composite + }) + + +def getinfo_binding2py(m): + return remove_default({ + "type": str(m.item_type), # EnumField in generate_composite + "address": m.address, # PrimitiveField in generate_composite + "port": m.port, # PrimitiveField in generate_composite + "socket": m.socket, # PrimitiveField in generate_composite + }) + + +def getinfo2py(m): + return remove_default({ + "id": hexlify(m.id), # PrimitiveField in generate_composite + "alias": m.alias, # PrimitiveField in generate_composite + "color": hexlify(m.color), # PrimitiveField in generate_composite + "num_peers": m.num_peers, # PrimitiveField in generate_composite + "num_pending_channels": m.num_pending_channels, # PrimitiveField in generate_composite + "num_active_channels": m.num_active_channels, # PrimitiveField in generate_composite + "num_inactive_channels": m.num_inactive_channels, # PrimitiveField in generate_composite + "version": m.version, # PrimitiveField in generate_composite + "lightning_dir": m.lightning_dir, # PrimitiveField in generate_composite + "blockheight": m.blockheight, # PrimitiveField in generate_composite + "network": m.network, # PrimitiveField in generate_composite + "fees_collected_msat": amount2msat(m.fees_collected_msat), # PrimitiveField in generate_composite + "address": [getinfo_address2py(i) for i in m.address], # ArrayField[composite] in generate_composite + "binding": [getinfo_binding2py(i) for i in m.binding], # ArrayField[composite] in generate_composite + "warning_bitcoind_sync": m.warning_bitcoind_sync, # PrimitiveField in generate_composite + "warning_lightningd_sync": m.warning_lightningd_sync, # PrimitiveField in generate_composite + }) + + +def listpeers_peers_log2py(m): + return remove_default({ + "type": str(m.item_type), # EnumField in generate_composite + "num_skipped": m.num_skipped, # PrimitiveField in generate_composite + "time": m.time, # PrimitiveField in generate_composite + "source": m.source, # PrimitiveField in generate_composite + "log": m.log, # PrimitiveField in generate_composite + "node_id": hexlify(m.node_id), # PrimitiveField in generate_composite + "data": hexlify(m.data), # PrimitiveField in generate_composite + }) + + +def listpeers_peers_channels_feerate2py(m): + return remove_default({ + "perkw": m.perkw, # PrimitiveField in generate_composite + "perkb": m.perkb, # PrimitiveField in generate_composite + }) + + +def listpeers_peers_channels_inflight2py(m): + return remove_default({ + "funding_txid": hexlify(m.funding_txid), # PrimitiveField in generate_composite + "funding_outnum": m.funding_outnum, # PrimitiveField in generate_composite + "feerate": m.feerate, # PrimitiveField in generate_composite + "total_funding_msat": amount2msat(m.total_funding_msat), # PrimitiveField in generate_composite + "our_funding_msat": amount2msat(m.our_funding_msat), # PrimitiveField in generate_composite + "scratch_txid": hexlify(m.scratch_txid), # PrimitiveField in generate_composite + }) + + +def listpeers_peers_channels_funding2py(m): + return remove_default({ + "local_msat": amount2msat(m.local_msat), # PrimitiveField in generate_composite + "remote_msat": amount2msat(m.remote_msat), # PrimitiveField in generate_composite + "pushed_msat": amount2msat(m.pushed_msat), # PrimitiveField in generate_composite + }) + + +def listpeers_peers_channels_state_changes2py(m): + return remove_default({ + "timestamp": m.timestamp, # PrimitiveField in generate_composite + "old_state": str(m.old_state), # EnumField in generate_composite + "new_state": str(m.new_state), # EnumField in generate_composite + "cause": str(m.cause), # EnumField in generate_composite + "message": m.message, # PrimitiveField in generate_composite + }) + + +def listpeers_peers_channels_htlcs2py(m): + return remove_default({ + "direction": str(m.direction), # EnumField in generate_composite + "id": m.id, # PrimitiveField in generate_composite + "amount_msat": amount2msat(m.amount_msat), # PrimitiveField in generate_composite + "expiry": m.expiry, # PrimitiveField in generate_composite + "payment_hash": hexlify(m.payment_hash), # PrimitiveField in generate_composite + "local_trimmed": m.local_trimmed, # PrimitiveField in generate_composite + "status": m.status, # PrimitiveField in generate_composite + "state": str(m.state), # EnumField in generate_composite + }) + + +def listpeers_peers_channels2py(m): + return remove_default({ + "state": str(m.state), # EnumField in generate_composite + "scratch_txid": hexlify(m.scratch_txid), # PrimitiveField in generate_composite + "owner": m.owner, # PrimitiveField in generate_composite + "short_channel_id": m.short_channel_id, # PrimitiveField in generate_composite + "channel_id": hexlify(m.channel_id), # PrimitiveField in generate_composite + "funding_txid": hexlify(m.funding_txid), # PrimitiveField in generate_composite + "funding_outnum": m.funding_outnum, # PrimitiveField in generate_composite + "initial_feerate": m.initial_feerate, # PrimitiveField in generate_composite + "last_feerate": m.last_feerate, # PrimitiveField in generate_composite + "next_feerate": m.next_feerate, # PrimitiveField in generate_composite + "next_fee_step": m.next_fee_step, # PrimitiveField in generate_composite + "inflight": [listpeers_peers_channels_inflight2py(i) for i in m.inflight], # ArrayField[composite] in generate_composite + "close_to": hexlify(m.close_to), # PrimitiveField in generate_composite + "private": m.private, # PrimitiveField in generate_composite + "opener": str(m.opener), # EnumField in generate_composite + "closer": str(m.closer), # EnumField in generate_composite + "features": [str(i) for i in m.features], # ArrayField[composite] in generate_composite + "to_us_msat": amount2msat(m.to_us_msat), # PrimitiveField in generate_composite + "min_to_us_msat": amount2msat(m.min_to_us_msat), # PrimitiveField in generate_composite + "max_to_us_msat": amount2msat(m.max_to_us_msat), # PrimitiveField in generate_composite + "total_msat": amount2msat(m.total_msat), # PrimitiveField in generate_composite + "fee_base_msat": amount2msat(m.fee_base_msat), # PrimitiveField in generate_composite + "fee_proportional_millionths": m.fee_proportional_millionths, # PrimitiveField in generate_composite + "dust_limit_msat": amount2msat(m.dust_limit_msat), # PrimitiveField in generate_composite + "max_total_htlc_in_msat": amount2msat(m.max_total_htlc_in_msat), # PrimitiveField in generate_composite + "their_reserve_msat": amount2msat(m.their_reserve_msat), # PrimitiveField in generate_composite + "our_reserve_msat": amount2msat(m.our_reserve_msat), # PrimitiveField in generate_composite + "spendable_msat": amount2msat(m.spendable_msat), # PrimitiveField in generate_composite + "receivable_msat": amount2msat(m.receivable_msat), # PrimitiveField in generate_composite + "minimum_htlc_in_msat": amount2msat(m.minimum_htlc_in_msat), # PrimitiveField in generate_composite + "minimum_htlc_out_msat": amount2msat(m.minimum_htlc_out_msat), # PrimitiveField in generate_composite + "maximum_htlc_out_msat": amount2msat(m.maximum_htlc_out_msat), # PrimitiveField in generate_composite + "their_to_self_delay": m.their_to_self_delay, # PrimitiveField in generate_composite + "our_to_self_delay": m.our_to_self_delay, # PrimitiveField in generate_composite + "max_accepted_htlcs": m.max_accepted_htlcs, # PrimitiveField in generate_composite + "state_changes": [listpeers_peers_channels_state_changes2py(i) for i in m.state_changes], # ArrayField[composite] in generate_composite + "status": [m.status for i in m.status], # ArrayField[primitive] in generate_composite + "in_payments_offered": m.in_payments_offered, # PrimitiveField in generate_composite + "in_offered_msat": amount2msat(m.in_offered_msat), # PrimitiveField in generate_composite + "in_payments_fulfilled": m.in_payments_fulfilled, # PrimitiveField in generate_composite + "in_fulfilled_msat": amount2msat(m.in_fulfilled_msat), # PrimitiveField in generate_composite + "out_payments_offered": m.out_payments_offered, # PrimitiveField in generate_composite + "out_offered_msat": amount2msat(m.out_offered_msat), # PrimitiveField in generate_composite + "out_payments_fulfilled": m.out_payments_fulfilled, # PrimitiveField in generate_composite + "out_fulfilled_msat": amount2msat(m.out_fulfilled_msat), # PrimitiveField in generate_composite + "htlcs": [listpeers_peers_channels_htlcs2py(i) for i in m.htlcs], # ArrayField[composite] in generate_composite + "close_to_addr": m.close_to_addr, # PrimitiveField in generate_composite + }) + + +def listpeers_peers2py(m): + return remove_default({ + "id": hexlify(m.id), # PrimitiveField in generate_composite + "connected": m.connected, # PrimitiveField in generate_composite + "log": [listpeers_peers_log2py(i) for i in m.log], # ArrayField[composite] in generate_composite + "channels": [listpeers_peers_channels2py(i) for i in m.channels], # ArrayField[composite] in generate_composite + "netaddr": [m.netaddr for i in m.netaddr], # ArrayField[primitive] in generate_composite + "remote_addr": m.remote_addr, # PrimitiveField in generate_composite + "features": hexlify(m.features), # PrimitiveField in generate_composite + }) + + +def listpeers2py(m): + return remove_default({ + "peers": [listpeers_peers2py(i) for i in m.peers], # ArrayField[composite] in generate_composite + }) + + +def listfunds_outputs2py(m): + return remove_default({ + "txid": hexlify(m.txid), # PrimitiveField in generate_composite + "output": m.output, # PrimitiveField in generate_composite + "amount_msat": amount2msat(m.amount_msat), # PrimitiveField in generate_composite + "scriptpubkey": hexlify(m.scriptpubkey), # PrimitiveField in generate_composite + "address": m.address, # PrimitiveField in generate_composite + "redeemscript": hexlify(m.redeemscript), # PrimitiveField in generate_composite + "status": str(m.status), # EnumField in generate_composite + "reserved": m.reserved, # PrimitiveField in generate_composite + "blockheight": m.blockheight, # PrimitiveField in generate_composite + }) + + +def listfunds_channels2py(m): + return remove_default({ + "peer_id": hexlify(m.peer_id), # PrimitiveField in generate_composite + "our_amount_msat": amount2msat(m.our_amount_msat), # PrimitiveField in generate_composite + "amount_msat": amount2msat(m.amount_msat), # PrimitiveField in generate_composite + "funding_txid": hexlify(m.funding_txid), # PrimitiveField in generate_composite + "funding_output": m.funding_output, # PrimitiveField in generate_composite + "connected": m.connected, # PrimitiveField in generate_composite + "state": str(m.state), # EnumField in generate_composite + "short_channel_id": m.short_channel_id, # PrimitiveField in generate_composite + }) + + +def listfunds2py(m): + return remove_default({ + "outputs": [listfunds_outputs2py(i) for i in m.outputs], # ArrayField[composite] in generate_composite + "channels": [listfunds_channels2py(i) for i in m.channels], # ArrayField[composite] in generate_composite + }) + + +def sendpay2py(m): + return remove_default({ + "id": m.id, # PrimitiveField in generate_composite + "groupid": m.groupid, # PrimitiveField in generate_composite + "payment_hash": hexlify(m.payment_hash), # PrimitiveField in generate_composite + "status": str(m.status), # EnumField in generate_composite + "amount_msat": amount2msat(m.amount_msat), # PrimitiveField in generate_composite + "destination": hexlify(m.destination), # PrimitiveField in generate_composite + "created_at": m.created_at, # PrimitiveField in generate_composite + "amount_sent_msat": amount2msat(m.amount_sent_msat), # PrimitiveField in generate_composite + "label": m.label, # PrimitiveField in generate_composite + "partid": m.partid, # PrimitiveField in generate_composite + "bolt11": m.bolt11, # PrimitiveField in generate_composite + "bolt12": m.bolt12, # PrimitiveField in generate_composite + "payment_preimage": hexlify(m.payment_preimage), # PrimitiveField in generate_composite + "message": m.message, # PrimitiveField in generate_composite + }) + + +def listchannels_channels2py(m): + return remove_default({ + "source": hexlify(m.source), # PrimitiveField in generate_composite + "destination": hexlify(m.destination), # PrimitiveField in generate_composite + "short_channel_id": m.short_channel_id, # PrimitiveField in generate_composite + "public": m.public, # PrimitiveField in generate_composite + "amount_msat": amount2msat(m.amount_msat), # PrimitiveField in generate_composite + "message_flags": m.message_flags, # PrimitiveField in generate_composite + "channel_flags": m.channel_flags, # PrimitiveField in generate_composite + "active": m.active, # PrimitiveField in generate_composite + "last_update": m.last_update, # PrimitiveField in generate_composite + "base_fee_millisatoshi": m.base_fee_millisatoshi, # PrimitiveField in generate_composite + "fee_per_millionth": m.fee_per_millionth, # PrimitiveField in generate_composite + "delay": m.delay, # PrimitiveField in generate_composite + "htlc_minimum_msat": amount2msat(m.htlc_minimum_msat), # PrimitiveField in generate_composite + "htlc_maximum_msat": amount2msat(m.htlc_maximum_msat), # PrimitiveField in generate_composite + "features": hexlify(m.features), # PrimitiveField in generate_composite + }) + + +def listchannels2py(m): + return remove_default({ + "channels": [listchannels_channels2py(i) for i in m.channels], # ArrayField[composite] in generate_composite + }) + + +def addgossip2py(m): + return remove_default({ + }) + + +def autocleaninvoice2py(m): + return remove_default({ + "enabled": m.enabled, # PrimitiveField in generate_composite + "expired_by": m.expired_by, # PrimitiveField in generate_composite + "cycle_seconds": m.cycle_seconds, # PrimitiveField in generate_composite + }) + + +def checkmessage2py(m): + return remove_default({ + "verified": m.verified, # PrimitiveField in generate_composite + "pubkey": hexlify(m.pubkey), # PrimitiveField in generate_composite + }) + + +def close2py(m): + return remove_default({ + "type": str(m.item_type), # EnumField in generate_composite + "tx": hexlify(m.tx), # PrimitiveField in generate_composite + "txid": hexlify(m.txid), # PrimitiveField in generate_composite + }) + + +def connect_address2py(m): + return remove_default({ + "type": str(m.item_type), # EnumField in generate_composite + "socket": m.socket, # PrimitiveField in generate_composite + "address": m.address, # PrimitiveField in generate_composite + "port": m.port, # PrimitiveField in generate_composite + }) + + +def connect2py(m): + return remove_default({ + "id": hexlify(m.id), # PrimitiveField in generate_composite + "features": hexlify(m.features), # PrimitiveField in generate_composite + "direction": str(m.direction), # EnumField in generate_composite + }) + + +def createinvoice2py(m): + return remove_default({ + "label": m.label, # PrimitiveField in generate_composite + "bolt11": m.bolt11, # PrimitiveField in generate_composite + "bolt12": m.bolt12, # PrimitiveField in generate_composite + "payment_hash": hexlify(m.payment_hash), # PrimitiveField in generate_composite + "amount_msat": amount2msat(m.amount_msat), # PrimitiveField in generate_composite + "status": str(m.status), # EnumField in generate_composite + "description": m.description, # PrimitiveField in generate_composite + "expires_at": m.expires_at, # PrimitiveField in generate_composite + "pay_index": m.pay_index, # PrimitiveField in generate_composite + "amount_received_msat": amount2msat(m.amount_received_msat), # PrimitiveField in generate_composite + "paid_at": m.paid_at, # PrimitiveField in generate_composite + "payment_preimage": hexlify(m.payment_preimage), # PrimitiveField in generate_composite + "local_offer_id": hexlify(m.local_offer_id), # PrimitiveField in generate_composite + "payer_note": m.payer_note, # PrimitiveField in generate_composite + }) + + +def datastore2py(m): + return remove_default({ + "key": [m.key for i in m.key], # ArrayField[primitive] in generate_composite + "generation": m.generation, # PrimitiveField in generate_composite + "hex": hexlify(m.hex), # PrimitiveField in generate_composite + "string": m.string, # PrimitiveField in generate_composite + }) + + +def createonion2py(m): + return remove_default({ + "onion": hexlify(m.onion), # PrimitiveField in generate_composite + "shared_secrets": [hexlify(m.shared_secrets) for i in hexlify(m.shared_secrets)], # ArrayField[primitive] in generate_composite + }) + + +def deldatastore2py(m): + return remove_default({ + "key": [m.key for i in m.key], # ArrayField[primitive] in generate_composite + "generation": m.generation, # PrimitiveField in generate_composite + "hex": hexlify(m.hex), # PrimitiveField in generate_composite + "string": m.string, # PrimitiveField in generate_composite + }) + + +def delexpiredinvoice2py(m): + return remove_default({ + }) + + +def delinvoice2py(m): + return remove_default({ + "label": m.label, # PrimitiveField in generate_composite + "bolt11": m.bolt11, # PrimitiveField in generate_composite + "bolt12": m.bolt12, # PrimitiveField in generate_composite + "amount_msat": amount2msat(m.amount_msat), # PrimitiveField in generate_composite + "description": m.description, # PrimitiveField in generate_composite + "payment_hash": hexlify(m.payment_hash), # PrimitiveField in generate_composite + "status": str(m.status), # EnumField in generate_composite + "expires_at": m.expires_at, # PrimitiveField in generate_composite + "local_offer_id": hexlify(m.local_offer_id), # PrimitiveField in generate_composite + "payer_note": m.payer_note, # PrimitiveField in generate_composite + }) + + +def invoice2py(m): + return remove_default({ + "bolt11": m.bolt11, # PrimitiveField in generate_composite + "payment_hash": hexlify(m.payment_hash), # PrimitiveField in generate_composite + "payment_secret": hexlify(m.payment_secret), # PrimitiveField in generate_composite + "expires_at": m.expires_at, # PrimitiveField in generate_composite + "warning_capacity": m.warning_capacity, # PrimitiveField in generate_composite + "warning_offline": m.warning_offline, # PrimitiveField in generate_composite + "warning_deadends": m.warning_deadends, # PrimitiveField in generate_composite + "warning_private_unused": m.warning_private_unused, # PrimitiveField in generate_composite + "warning_mpp": m.warning_mpp, # PrimitiveField in generate_composite + }) + + +def listdatastore_datastore2py(m): + return remove_default({ + "key": [m.key for i in m.key], # ArrayField[primitive] in generate_composite + "generation": m.generation, # PrimitiveField in generate_composite + "hex": hexlify(m.hex), # PrimitiveField in generate_composite + "string": m.string, # PrimitiveField in generate_composite + }) + + +def listdatastore2py(m): + return remove_default({ + "datastore": [listdatastore_datastore2py(i) for i in m.datastore], # ArrayField[composite] in generate_composite + }) + + +def listinvoices_invoices2py(m): + return remove_default({ + "label": m.label, # PrimitiveField in generate_composite + "description": m.description, # PrimitiveField in generate_composite + "payment_hash": hexlify(m.payment_hash), # PrimitiveField in generate_composite + "status": str(m.status), # EnumField in generate_composite + "expires_at": m.expires_at, # PrimitiveField in generate_composite + "amount_msat": amount2msat(m.amount_msat), # PrimitiveField in generate_composite + "bolt11": m.bolt11, # PrimitiveField in generate_composite + "bolt12": m.bolt12, # PrimitiveField in generate_composite + "local_offer_id": hexlify(m.local_offer_id), # PrimitiveField in generate_composite + "payer_note": m.payer_note, # PrimitiveField in generate_composite + "pay_index": m.pay_index, # PrimitiveField in generate_composite + "amount_received_msat": amount2msat(m.amount_received_msat), # PrimitiveField in generate_composite + "paid_at": m.paid_at, # PrimitiveField in generate_composite + "payment_preimage": hexlify(m.payment_preimage), # PrimitiveField in generate_composite + }) + + +def listinvoices2py(m): + return remove_default({ + "invoices": [listinvoices_invoices2py(i) for i in m.invoices], # ArrayField[composite] in generate_composite + }) + + +def sendonion2py(m): + return remove_default({ + "id": m.id, # PrimitiveField in generate_composite + "payment_hash": hexlify(m.payment_hash), # PrimitiveField in generate_composite + "status": str(m.status), # EnumField in generate_composite + "amount_msat": amount2msat(m.amount_msat), # PrimitiveField in generate_composite + "destination": hexlify(m.destination), # PrimitiveField in generate_composite + "created_at": m.created_at, # PrimitiveField in generate_composite + "amount_sent_msat": amount2msat(m.amount_sent_msat), # PrimitiveField in generate_composite + "label": m.label, # PrimitiveField in generate_composite + "bolt11": m.bolt11, # PrimitiveField in generate_composite + "bolt12": m.bolt12, # PrimitiveField in generate_composite + "partid": m.partid, # PrimitiveField in generate_composite + "payment_preimage": hexlify(m.payment_preimage), # PrimitiveField in generate_composite + "message": m.message, # PrimitiveField in generate_composite + }) + + +def listsendpays_payments2py(m): + return remove_default({ + "id": m.id, # PrimitiveField in generate_composite + "groupid": m.groupid, # PrimitiveField in generate_composite + "payment_hash": hexlify(m.payment_hash), # PrimitiveField in generate_composite + "status": str(m.status), # EnumField in generate_composite + "amount_msat": amount2msat(m.amount_msat), # PrimitiveField in generate_composite + "destination": hexlify(m.destination), # PrimitiveField in generate_composite + "created_at": m.created_at, # PrimitiveField in generate_composite + "amount_sent_msat": amount2msat(m.amount_sent_msat), # PrimitiveField in generate_composite + "label": m.label, # PrimitiveField in generate_composite + "bolt11": m.bolt11, # PrimitiveField in generate_composite + "description": m.description, # PrimitiveField in generate_composite + "bolt12": m.bolt12, # PrimitiveField in generate_composite + "payment_preimage": hexlify(m.payment_preimage), # PrimitiveField in generate_composite + "erroronion": hexlify(m.erroronion), # PrimitiveField in generate_composite + }) + + +def listsendpays2py(m): + return remove_default({ + "payments": [listsendpays_payments2py(i) for i in m.payments], # ArrayField[composite] in generate_composite + }) + + +def listtransactions_transactions_inputs2py(m): + return remove_default({ + "txid": hexlify(m.txid), # PrimitiveField in generate_composite + "index": m.index, # PrimitiveField in generate_composite + "sequence": m.sequence, # PrimitiveField in generate_composite + "type": str(m.item_type), # EnumField in generate_composite + "channel": m.channel, # PrimitiveField in generate_composite + }) + + +def listtransactions_transactions_outputs2py(m): + return remove_default({ + "index": m.index, # PrimitiveField in generate_composite + "amount_msat": amount2msat(m.amount_msat), # PrimitiveField in generate_composite + "script_pub_key": hexlify(m.script_pub_key), # PrimitiveField in generate_composite + "type": str(m.item_type), # EnumField in generate_composite + "channel": m.channel, # PrimitiveField in generate_composite + }) + + +def listtransactions_transactions2py(m): + return remove_default({ + "hash": hexlify(m.hash), # PrimitiveField in generate_composite + "rawtx": hexlify(m.rawtx), # PrimitiveField in generate_composite + "blockheight": m.blockheight, # PrimitiveField in generate_composite + "txindex": m.txindex, # PrimitiveField in generate_composite + "type": [str(i) for i in m.type], # ArrayField[composite] in generate_composite + "channel": m.channel, # PrimitiveField in generate_composite + "locktime": m.locktime, # PrimitiveField in generate_composite + "version": m.version, # PrimitiveField in generate_composite + "inputs": [listtransactions_transactions_inputs2py(i) for i in m.inputs], # ArrayField[composite] in generate_composite + "outputs": [listtransactions_transactions_outputs2py(i) for i in m.outputs], # ArrayField[composite] in generate_composite + }) + + +def listtransactions2py(m): + return remove_default({ + "transactions": [listtransactions_transactions2py(i) for i in m.transactions], # ArrayField[composite] in generate_composite + }) + + +def pay2py(m): + return remove_default({ + "payment_preimage": hexlify(m.payment_preimage), # PrimitiveField in generate_composite + "destination": hexlify(m.destination), # PrimitiveField in generate_composite + "payment_hash": hexlify(m.payment_hash), # PrimitiveField in generate_composite + "created_at": m.created_at, # PrimitiveField in generate_composite + "parts": m.parts, # PrimitiveField in generate_composite + "amount_msat": amount2msat(m.amount_msat), # PrimitiveField in generate_composite + "amount_sent_msat": amount2msat(m.amount_sent_msat), # PrimitiveField in generate_composite + "warning_partial_completion": m.warning_partial_completion, # PrimitiveField in generate_composite + "status": str(m.status), # EnumField in generate_composite + }) + + +def listnodes_nodes_addresses2py(m): + return remove_default({ + "type": str(m.item_type), # EnumField in generate_composite + "port": m.port, # PrimitiveField in generate_composite + "address": m.address, # PrimitiveField in generate_composite + }) + + +def listnodes_nodes2py(m): + return remove_default({ + "nodeid": hexlify(m.nodeid), # PrimitiveField in generate_composite + "last_timestamp": m.last_timestamp, # PrimitiveField in generate_composite + "alias": m.alias, # PrimitiveField in generate_composite + "color": hexlify(m.color), # PrimitiveField in generate_composite + "features": hexlify(m.features), # PrimitiveField in generate_composite + "addresses": [listnodes_nodes_addresses2py(i) for i in m.addresses], # ArrayField[composite] in generate_composite + }) + + +def listnodes2py(m): + return remove_default({ + "nodes": [listnodes_nodes2py(i) for i in m.nodes], # ArrayField[composite] in generate_composite + }) + + +def waitanyinvoice2py(m): + return remove_default({ + "label": m.label, # PrimitiveField in generate_composite + "description": m.description, # PrimitiveField in generate_composite + "payment_hash": hexlify(m.payment_hash), # PrimitiveField in generate_composite + "status": str(m.status), # EnumField in generate_composite + "expires_at": m.expires_at, # PrimitiveField in generate_composite + "amount_msat": amount2msat(m.amount_msat), # PrimitiveField in generate_composite + "bolt11": m.bolt11, # PrimitiveField in generate_composite + "bolt12": m.bolt12, # PrimitiveField in generate_composite + "pay_index": m.pay_index, # PrimitiveField in generate_composite + "amount_received_msat": amount2msat(m.amount_received_msat), # PrimitiveField in generate_composite + "paid_at": m.paid_at, # PrimitiveField in generate_composite + "payment_preimage": hexlify(m.payment_preimage), # PrimitiveField in generate_composite + }) + + +def waitinvoice2py(m): + return remove_default({ + "label": m.label, # PrimitiveField in generate_composite + "description": m.description, # PrimitiveField in generate_composite + "payment_hash": hexlify(m.payment_hash), # PrimitiveField in generate_composite + "status": str(m.status), # EnumField in generate_composite + "expires_at": m.expires_at, # PrimitiveField in generate_composite + "amount_msat": amount2msat(m.amount_msat), # PrimitiveField in generate_composite + "bolt11": m.bolt11, # PrimitiveField in generate_composite + "bolt12": m.bolt12, # PrimitiveField in generate_composite + "pay_index": m.pay_index, # PrimitiveField in generate_composite + "amount_received_msat": amount2msat(m.amount_received_msat), # PrimitiveField in generate_composite + "paid_at": m.paid_at, # PrimitiveField in generate_composite + "payment_preimage": hexlify(m.payment_preimage), # PrimitiveField in generate_composite + }) + + +def waitsendpay2py(m): + return remove_default({ + "id": m.id, # PrimitiveField in generate_composite + "groupid": m.groupid, # PrimitiveField in generate_composite + "payment_hash": hexlify(m.payment_hash), # PrimitiveField in generate_composite + "status": str(m.status), # EnumField in generate_composite + "amount_msat": amount2msat(m.amount_msat), # PrimitiveField in generate_composite + "destination": hexlify(m.destination), # PrimitiveField in generate_composite + "created_at": m.created_at, # PrimitiveField in generate_composite + "amount_sent_msat": amount2msat(m.amount_sent_msat), # PrimitiveField in generate_composite + "label": m.label, # PrimitiveField in generate_composite + "partid": m.partid, # PrimitiveField in generate_composite + "bolt11": m.bolt11, # PrimitiveField in generate_composite + "bolt12": m.bolt12, # PrimitiveField in generate_composite + "payment_preimage": hexlify(m.payment_preimage), # PrimitiveField in generate_composite + }) + + +def newaddr2py(m): + return remove_default({ + "bech32": m.bech32, # PrimitiveField in generate_composite + "p2sh_segwit": m.p2sh_segwit, # PrimitiveField in generate_composite + }) + + +def withdraw2py(m): + return remove_default({ + "tx": hexlify(m.tx), # PrimitiveField in generate_composite + "txid": hexlify(m.txid), # PrimitiveField in generate_composite + "psbt": m.psbt, # PrimitiveField in generate_composite + }) + + +def keysend2py(m): + return remove_default({ + "payment_preimage": hexlify(m.payment_preimage), # PrimitiveField in generate_composite + "destination": hexlify(m.destination), # PrimitiveField in generate_composite + "payment_hash": hexlify(m.payment_hash), # PrimitiveField in generate_composite + "created_at": m.created_at, # PrimitiveField in generate_composite + "parts": m.parts, # PrimitiveField in generate_composite + "amount_msat": amount2msat(m.amount_msat), # PrimitiveField in generate_composite + "amount_sent_msat": amount2msat(m.amount_sent_msat), # PrimitiveField in generate_composite + "warning_partial_completion": m.warning_partial_completion, # PrimitiveField in generate_composite + "status": str(m.status), # EnumField in generate_composite + }) + + +def fundpsbt_reservations2py(m): + return remove_default({ + "txid": hexlify(m.txid), # PrimitiveField in generate_composite + "vout": m.vout, # PrimitiveField in generate_composite + "was_reserved": m.was_reserved, # PrimitiveField in generate_composite + "reserved": m.reserved, # PrimitiveField in generate_composite + "reserved_to_block": m.reserved_to_block, # PrimitiveField in generate_composite + }) + + +def fundpsbt2py(m): + return remove_default({ + "psbt": m.psbt, # PrimitiveField in generate_composite + "feerate_per_kw": m.feerate_per_kw, # PrimitiveField in generate_composite + "estimated_final_weight": m.estimated_final_weight, # PrimitiveField in generate_composite + "excess_msat": amount2msat(m.excess_msat), # PrimitiveField in generate_composite + "change_outnum": m.change_outnum, # PrimitiveField in generate_composite + "reservations": [fundpsbt_reservations2py(i) for i in m.reservations], # ArrayField[composite] in generate_composite + }) + + +def sendpsbt2py(m): + return remove_default({ + "tx": hexlify(m.tx), # PrimitiveField in generate_composite + "txid": hexlify(m.txid), # PrimitiveField in generate_composite + }) + + +def signpsbt2py(m): + return remove_default({ + "signed_psbt": m.signed_psbt, # PrimitiveField in generate_composite + }) + + +def utxopsbt_reservations2py(m): + return remove_default({ + "txid": hexlify(m.txid), # PrimitiveField in generate_composite + "vout": m.vout, # PrimitiveField in generate_composite + "was_reserved": m.was_reserved, # PrimitiveField in generate_composite + "reserved": m.reserved, # PrimitiveField in generate_composite + "reserved_to_block": m.reserved_to_block, # PrimitiveField in generate_composite + }) + + +def utxopsbt2py(m): + return remove_default({ + "psbt": m.psbt, # PrimitiveField in generate_composite + "feerate_per_kw": m.feerate_per_kw, # PrimitiveField in generate_composite + "estimated_final_weight": m.estimated_final_weight, # PrimitiveField in generate_composite + "excess_msat": amount2msat(m.excess_msat), # PrimitiveField in generate_composite + "change_outnum": m.change_outnum, # PrimitiveField in generate_composite + "reservations": [utxopsbt_reservations2py(i) for i in m.reservations], # ArrayField[composite] in generate_composite + }) + + +def txdiscard2py(m): + return remove_default({ + "unsigned_tx": hexlify(m.unsigned_tx), # PrimitiveField in generate_composite + "txid": hexlify(m.txid), # PrimitiveField in generate_composite + }) + + +def txprepare2py(m): + return remove_default({ + "psbt": m.psbt, # PrimitiveField in generate_composite + "unsigned_tx": hexlify(m.unsigned_tx), # PrimitiveField in generate_composite + "txid": hexlify(m.txid), # PrimitiveField in generate_composite + }) + + +def txsend2py(m): + return remove_default({ + "psbt": m.psbt, # PrimitiveField in generate_composite + "tx": hexlify(m.tx), # PrimitiveField in generate_composite + "txid": hexlify(m.txid), # PrimitiveField in generate_composite + }) + + +def disconnect2py(m): + return remove_default({ + }) + + +def feerates_perkb2py(m): + return remove_default({ + "min_acceptable": m.min_acceptable, # PrimitiveField in generate_composite + "max_acceptable": m.max_acceptable, # PrimitiveField in generate_composite + "opening": m.opening, # PrimitiveField in generate_composite + "mutual_close": m.mutual_close, # PrimitiveField in generate_composite + "unilateral_close": m.unilateral_close, # PrimitiveField in generate_composite + "delayed_to_us": m.delayed_to_us, # PrimitiveField in generate_composite + "htlc_resolution": m.htlc_resolution, # PrimitiveField in generate_composite + "penalty": m.penalty, # PrimitiveField in generate_composite + }) + + +def feerates_perkw2py(m): + return remove_default({ + "min_acceptable": m.min_acceptable, # PrimitiveField in generate_composite + "max_acceptable": m.max_acceptable, # PrimitiveField in generate_composite + "opening": m.opening, # PrimitiveField in generate_composite + "mutual_close": m.mutual_close, # PrimitiveField in generate_composite + "unilateral_close": m.unilateral_close, # PrimitiveField in generate_composite + "delayed_to_us": m.delayed_to_us, # PrimitiveField in generate_composite + "htlc_resolution": m.htlc_resolution, # PrimitiveField in generate_composite + "penalty": m.penalty, # PrimitiveField in generate_composite + }) + + +def feerates_onchain_fee_estimates2py(m): + return remove_default({ + "opening_channel_satoshis": m.opening_channel_satoshis, # PrimitiveField in generate_composite + "mutual_close_satoshis": m.mutual_close_satoshis, # PrimitiveField in generate_composite + "unilateral_close_satoshis": m.unilateral_close_satoshis, # PrimitiveField in generate_composite + "htlc_timeout_satoshis": m.htlc_timeout_satoshis, # PrimitiveField in generate_composite + "htlc_success_satoshis": m.htlc_success_satoshis, # PrimitiveField in generate_composite + }) + + +def feerates2py(m): + return remove_default({ + "warning_missing_feerates": m.warning_missing_feerates, # PrimitiveField in generate_composite + }) + + +def getroute_route2py(m): + return remove_default({ + "id": hexlify(m.id), # PrimitiveField in generate_composite + "channel": m.channel, # PrimitiveField in generate_composite + "direction": m.direction, # PrimitiveField in generate_composite + "amount_msat": amount2msat(m.amount_msat), # PrimitiveField in generate_composite + "delay": m.delay, # PrimitiveField in generate_composite + "style": str(m.style), # EnumField in generate_composite + }) + + +def getroute2py(m): + return remove_default({ + "route": [getroute_route2py(i) for i in m.route], # ArrayField[composite] in generate_composite + }) + + +def listforwards_forwards2py(m): + return remove_default({ + "in_channel": m.in_channel, # PrimitiveField in generate_composite + "in_msat": amount2msat(m.in_msat), # PrimitiveField in generate_composite + "status": str(m.status), # EnumField in generate_composite + "received_time": m.received_time, # PrimitiveField in generate_composite + "out_channel": m.out_channel, # PrimitiveField in generate_composite + "payment_hash": hexlify(m.payment_hash), # PrimitiveField in generate_composite + "style": str(m.style), # EnumField in generate_composite + "fee_msat": amount2msat(m.fee_msat), # PrimitiveField in generate_composite + "out_msat": amount2msat(m.out_msat), # PrimitiveField in generate_composite + }) + + +def listforwards2py(m): + return remove_default({ + "forwards": [listforwards_forwards2py(i) for i in m.forwards], # ArrayField[composite] in generate_composite + }) + + +def listpays_pays2py(m): + return remove_default({ + "payment_hash": hexlify(m.payment_hash), # PrimitiveField in generate_composite + "status": str(m.status), # EnumField in generate_composite + "destination": hexlify(m.destination), # PrimitiveField in generate_composite + "created_at": m.created_at, # PrimitiveField in generate_composite + "label": m.label, # PrimitiveField in generate_composite + "bolt11": m.bolt11, # PrimitiveField in generate_composite + "description": m.description, # PrimitiveField in generate_composite + "bolt12": m.bolt12, # PrimitiveField in generate_composite + "amount_msat": amount2msat(m.amount_msat), # PrimitiveField in generate_composite + "amount_sent_msat": amount2msat(m.amount_sent_msat), # PrimitiveField in generate_composite + "erroronion": hexlify(m.erroronion), # PrimitiveField in generate_composite + }) + + +def listpays2py(m): + return remove_default({ + "pays": [listpays_pays2py(i) for i in m.pays], # ArrayField[composite] in generate_composite + }) + + +def ping2py(m): + return remove_default({ + "totlen": m.totlen, # PrimitiveField in generate_composite + }) + + +def signmessage2py(m): + return remove_default({ + "signature": hexlify(m.signature), # PrimitiveField in generate_composite + "recid": hexlify(m.recid), # PrimitiveField in generate_composite + "zbase": m.zbase, # PrimitiveField in generate_composite + })