diff --git a/Cargo.lock b/Cargo.lock index ffe39de1f..39d8c4bd4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -429,6 +429,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "43d193de1f7487df1914d3a568b772458861d33f9c54249612cc2893d6915054" dependencies = [ "bitcoin_hashes 0.13.0", + "rand", "rand_core", "serde", "unicode-normalization", @@ -1434,6 +1435,7 @@ checksum = "e629b9b98ef3dd8afe6ca2bd0f89306cec16d43d907889945bc5d6687f2f13c7" name = "gl-cli" version = "0.1.3" dependencies = [ + "bip39", "clap", "dirs", "env_logger 0.11.8", @@ -1576,6 +1578,7 @@ dependencies = [ "once_cell", "thiserror 2.0.17", "tokio", + "tonic 0.11.0", "tracing", "uniffi", ] diff --git a/Cargo.toml b/Cargo.toml index 2d34add74..52e29dba9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -30,6 +30,7 @@ env_logger = "0.10" cln-grpc = "0.4" cln-rpc = "0.4" cln-plugin = "0.4" +tonic = "0.11" vls-core = "^0.14" vls-persist = "^0.14" diff --git a/libs/gl-client-py/glclient/__init__.py b/libs/gl-client-py/glclient/__init__.py index ae90422cb..247c3a441 100644 --- a/libs/gl-client-py/glclient/__init__.py +++ b/libs/gl-client-py/glclient/__init__.py @@ -448,21 +448,22 @@ def stream_log(self): break yield nodepb.LogEntry.FromString(bytes(n)) - def stream_incoming(self): - stream = self.inner.stream_incoming(b"") + def stream_custommsg(self): + stream = self.inner.stream_custommsg(b"") while True: n = stream.next() if n is None: break - yield nodepb.IncomingPayment.FromString(bytes(n)) + yield nodepb.Custommsg.FromString(bytes(n)) - def stream_custommsg(self): - stream = self.inner.stream_custommsg(b"") + def stream_node_events(self): + """Stream node events (invoice payments, peer changes, etc.) as they occur.""" + stream = self.inner.stream_node_events(b"") while True: n = stream.next() if n is None: break - yield nodepb.Custommsg.FromString(bytes(n)) + yield nodepb.NodeEvent.FromString(bytes(n)) def send_custommsg(self, node_id: str, msg: bytes) -> clnpb.SendcustommsgResponse: uri = "/cln.Node/SendCustomMsg" diff --git a/libs/gl-client-py/glclient/greenlight.proto b/libs/gl-client-py/glclient/greenlight.proto index 63dd182c0..ba9528a6d 100644 --- a/libs/gl-client-py/glclient/greenlight.proto +++ b/libs/gl-client-py/glclient/greenlight.proto @@ -25,7 +25,6 @@ service Node { // // Currently includes off-chain payments received matching an // invoice or spontaneus paymens through keysend. - rpc StreamIncoming(StreamIncomingFilter) returns (stream IncomingPayment) {} // Stream the logs as they are produced by the node // @@ -43,6 +42,14 @@ service Node { // replayed if the stream is interrupted. rpc StreamCustommsg(StreamCustommsgRequest) returns (stream Custommsg) {} + // Stream node events in real-time. + // + // This is a unified event stream that delivers various node events + // as they occur, including invoice updates, peer changes, channel + // state changes, and balance updates. Events are not persisted and + // will not be replayed if the stream is interrupted. + rpc StreamNodeEvents(NodeEventsRequest) returns (stream NodeEvent) {} + //////////////////////////////// HSM Messages //////////////////////// // // The following messages are related to communicating HSM @@ -113,9 +120,6 @@ message Amount { } } -// Options to stream_incoming to specify what to stream. -message StreamIncomingFilter { -} message TlvField { uint64 type = 1; @@ -243,3 +247,38 @@ message LspInvoiceResponse { bytes payment_hash = 4; bytes payment_secret = 5; } + +// Request for streaming node events. Currently empty but defined as +// its own message type to allow adding filters in the future (e.g., +// filter by event type, invoice label, etc.) +message NodeEventsRequest { +} + +// A real-time event from the node. Uses oneof to discriminate between +// different event types. +message NodeEvent { + oneof event { + InvoicePaid invoice_paid = 1; + // Future event types: + // PeerConnected peer_connected = 2; + // PeerDisconnected peer_disconnected = 3; + // ChannelStateChanged channel_state_changed = 4; + // BalanceChanged balance_changed = 5; + } +} + +// Event emitted when an invoice is paid. +message InvoicePaid { + // The payment hash of the paid invoice. + bytes payment_hash = 1; + // The bolt11 invoice string. + string bolt11 = 2; + // The preimage that proves payment. + bytes preimage = 3; + // The label assigned to the invoice. + string label = 4; + // Amount received in millisatoshis. + uint64 amount_msat = 5; + // Extra TLV fields included in the payment. + repeated TlvField extratlvs = 6; +} diff --git a/libs/gl-client-py/glclient/greenlight_pb2.py b/libs/gl-client-py/glclient/greenlight_pb2.py index 3c2ab0bef..ebb94eb6c 100644 --- a/libs/gl-client-py/glclient/greenlight_pb2.py +++ b/libs/gl-client-py/glclient/greenlight_pb2.py @@ -24,7 +24,7 @@ -DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x19glclient/greenlight.proto\x12\ngreenlight\"H\n\x11HsmRequestContext\x12\x0f\n\x07node_id\x18\x01 \x01(\x0c\x12\x0c\n\x04\x64\x62id\x18\x02 \x01(\x04\x12\x14\n\x0c\x63\x61pabilities\x18\x03 \x01(\x04\"q\n\x0bHsmResponse\x12\x12\n\nrequest_id\x18\x01 \x01(\r\x12\x0b\n\x03raw\x18\x02 \x01(\x0c\x12\x32\n\x0csigner_state\x18\x05 \x03(\x0b\x32\x1c.greenlight.SignerStateEntry\x12\r\n\x05\x65rror\x18\x06 \x01(\t\"\xbf\x01\n\nHsmRequest\x12\x12\n\nrequest_id\x18\x01 \x01(\r\x12.\n\x07\x63ontext\x18\x02 \x01(\x0b\x32\x1d.greenlight.HsmRequestContext\x12\x0b\n\x03raw\x18\x03 \x01(\x0c\x12\x32\n\x0csigner_state\x18\x04 \x03(\x0b\x32\x1c.greenlight.SignerStateEntry\x12,\n\x08requests\x18\x05 \x03(\x0b\x32\x1a.greenlight.PendingRequest\"\x07\n\x05\x45mpty\"l\n\x06\x41mount\x12\x16\n\x0cmillisatoshi\x18\x01 \x01(\x04H\x00\x12\x11\n\x07satoshi\x18\x02 \x01(\x04H\x00\x12\x11\n\x07\x62itcoin\x18\x03 \x01(\x04H\x00\x12\r\n\x03\x61ll\x18\x04 \x01(\x08H\x00\x12\r\n\x03\x61ny\x18\x05 \x01(\x08H\x00\x42\x06\n\x04unit\"\x16\n\x14StreamIncomingFilter\"\'\n\x08TlvField\x12\x0c\n\x04type\x18\x01 \x01(\x04\x12\r\n\x05value\x18\x02 \x01(\x0c\"\xa5\x01\n\x0fOffChainPayment\x12\r\n\x05label\x18\x01 \x01(\t\x12\x10\n\x08preimage\x18\x02 \x01(\x0c\x12\"\n\x06\x61mount\x18\x03 \x01(\x0b\x32\x12.greenlight.Amount\x12\'\n\textratlvs\x18\x04 \x03(\x0b\x32\x14.greenlight.TlvField\x12\x14\n\x0cpayment_hash\x18\x05 \x01(\x0c\x12\x0e\n\x06\x62olt11\x18\x06 \x01(\t\"M\n\x0fIncomingPayment\x12/\n\x08offchain\x18\x01 \x01(\x0b\x32\x1b.greenlight.OffChainPaymentH\x00\x42\t\n\x07\x64\x65tails\"\x12\n\x10StreamLogRequest\"\x18\n\x08LogEntry\x12\x0c\n\x04line\x18\x01 \x01(\t\"?\n\x10SignerStateEntry\x12\x0f\n\x07version\x18\x01 \x01(\x04\x12\x0b\n\x03key\x18\x02 \x01(\t\x12\r\n\x05value\x18\x03 \x01(\x0c\"r\n\x0ePendingRequest\x12\x0f\n\x07request\x18\x01 \x01(\x0c\x12\x0b\n\x03uri\x18\x02 \x01(\t\x12\x11\n\tsignature\x18\x03 \x01(\x0c\x12\x0e\n\x06pubkey\x18\x04 \x01(\x0c\x12\x11\n\ttimestamp\x18\x05 \x01(\x04\x12\x0c\n\x04rune\x18\x06 \x01(\x0c\"=\n\nNodeConfig\x12/\n\x0bstartupmsgs\x18\x01 \x03(\x0b\x32\x1a.greenlight.StartupMessage\"!\n\x08GlConfig\x12\x15\n\rclose_to_addr\x18\x01 \x01(\t\"3\n\x0eStartupMessage\x12\x0f\n\x07request\x18\x01 \x01(\x0c\x12\x10\n\x08response\x18\x02 \x01(\x0c\"\x18\n\x16StreamCustommsgRequest\"-\n\tCustommsg\x12\x0f\n\x07peer_id\x18\x01 \x01(\x0c\x12\x0f\n\x07payload\x18\x02 \x01(\x0c\"\xa4\x01\n\x14TrampolinePayRequest\x12\x0e\n\x06\x62olt11\x18\x01 \x01(\t\x12\x1a\n\x12trampoline_node_id\x18\x02 \x01(\x0c\x12\x13\n\x0b\x61mount_msat\x18\x03 \x01(\x04\x12\r\n\x05label\x18\x04 \x01(\t\x12\x15\n\rmaxfeepercent\x18\x05 \x01(\x02\x12\x10\n\x08maxdelay\x18\x06 \x01(\r\x12\x13\n\x0b\x64\x65scription\x18\x07 \x01(\t\"\xd5\x01\n\x15TrampolinePayResponse\x12\x18\n\x10payment_preimage\x18\x01 \x01(\x0c\x12\x14\n\x0cpayment_hash\x18\x02 \x01(\x0c\x12\x12\n\ncreated_at\x18\x03 \x01(\x01\x12\r\n\x05parts\x18\x04 \x01(\r\x12\x13\n\x0b\x61mount_msat\x18\x05 \x01(\x04\x12\x18\n\x10\x61mount_sent_msat\x18\x06 \x01(\x04\x12\x13\n\x0b\x64\x65stination\x18\x07 \x01(\x0c\"%\n\tPayStatus\x12\x0c\n\x08\x43OMPLETE\x10\x00\x12\n\n\x06\x46\x41ILED\x10\x02\"k\n\x11LspInvoiceRequest\x12\x0e\n\x06lsp_id\x18\x01 \x01(\t\x12\r\n\x05token\x18\x02 \x01(\t\x12\x13\n\x0b\x61mount_msat\x18\x03 \x01(\x04\x12\x13\n\x0b\x64\x65scription\x18\x04 \x01(\t\x12\r\n\x05label\x18\x05 \x01(\t\"}\n\x12LspInvoiceResponse\x12\x0e\n\x06\x62olt11\x18\x01 \x01(\t\x12\x15\n\rcreated_index\x18\x02 \x01(\r\x12\x12\n\nexpires_at\x18\x03 \x01(\r\x12\x14\n\x0cpayment_hash\x18\x04 \x01(\x0c\x12\x16\n\x0epayment_secret\x18\x05 \x01(\x0c\x32\xd8\x04\n\x04Node\x12M\n\nLspInvoice\x12\x1d.greenlight.LspInvoiceRequest\x1a\x1e.greenlight.LspInvoiceResponse\"\x00\x12S\n\x0eStreamIncoming\x12 .greenlight.StreamIncomingFilter\x1a\x1b.greenlight.IncomingPayment\"\x00\x30\x01\x12\x43\n\tStreamLog\x12\x1c.greenlight.StreamLogRequest\x1a\x14.greenlight.LogEntry\"\x00\x30\x01\x12P\n\x0fStreamCustommsg\x12\".greenlight.StreamCustommsgRequest\x1a\x15.greenlight.Custommsg\"\x00\x30\x01\x12\x42\n\x11StreamHsmRequests\x12\x11.greenlight.Empty\x1a\x16.greenlight.HsmRequest\"\x00\x30\x01\x12\x41\n\x11RespondHsmRequest\x12\x17.greenlight.HsmResponse\x1a\x11.greenlight.Empty\"\x00\x12\x36\n\tConfigure\x12\x14.greenlight.GlConfig\x1a\x11.greenlight.Empty\"\x00\x12V\n\rTrampolinePay\x12 .greenlight.TrampolinePayRequest\x1a!.greenlight.TrampolinePayResponse\"\x00\x32s\n\x03Hsm\x12<\n\x07Request\x12\x16.greenlight.HsmRequest\x1a\x17.greenlight.HsmResponse\"\x00\x12.\n\x04Ping\x12\x11.greenlight.Empty\x1a\x11.greenlight.Empty\"\x00\x62\x06proto3') +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x19glclient/greenlight.proto\x12\ngreenlight\"H\n\x11HsmRequestContext\x12\x0f\n\x07node_id\x18\x01 \x01(\x0c\x12\x0c\n\x04\x64\x62id\x18\x02 \x01(\x04\x12\x14\n\x0c\x63\x61pabilities\x18\x03 \x01(\x04\"q\n\x0bHsmResponse\x12\x12\n\nrequest_id\x18\x01 \x01(\r\x12\x0b\n\x03raw\x18\x02 \x01(\x0c\x12\x32\n\x0csigner_state\x18\x05 \x03(\x0b\x32\x1c.greenlight.SignerStateEntry\x12\r\n\x05\x65rror\x18\x06 \x01(\t\"\xbf\x01\n\nHsmRequest\x12\x12\n\nrequest_id\x18\x01 \x01(\r\x12.\n\x07\x63ontext\x18\x02 \x01(\x0b\x32\x1d.greenlight.HsmRequestContext\x12\x0b\n\x03raw\x18\x03 \x01(\x0c\x12\x32\n\x0csigner_state\x18\x04 \x03(\x0b\x32\x1c.greenlight.SignerStateEntry\x12,\n\x08requests\x18\x05 \x03(\x0b\x32\x1a.greenlight.PendingRequest\"\x07\n\x05\x45mpty\"l\n\x06\x41mount\x12\x16\n\x0cmillisatoshi\x18\x01 \x01(\x04H\x00\x12\x11\n\x07satoshi\x18\x02 \x01(\x04H\x00\x12\x11\n\x07\x62itcoin\x18\x03 \x01(\x04H\x00\x12\r\n\x03\x61ll\x18\x04 \x01(\x08H\x00\x12\r\n\x03\x61ny\x18\x05 \x01(\x08H\x00\x42\x06\n\x04unit\"\'\n\x08TlvField\x12\x0c\n\x04type\x18\x01 \x01(\x04\x12\r\n\x05value\x18\x02 \x01(\x0c\"\xa5\x01\n\x0fOffChainPayment\x12\r\n\x05label\x18\x01 \x01(\t\x12\x10\n\x08preimage\x18\x02 \x01(\x0c\x12\"\n\x06\x61mount\x18\x03 \x01(\x0b\x32\x12.greenlight.Amount\x12\'\n\textratlvs\x18\x04 \x03(\x0b\x32\x14.greenlight.TlvField\x12\x14\n\x0cpayment_hash\x18\x05 \x01(\x0c\x12\x0e\n\x06\x62olt11\x18\x06 \x01(\t\"M\n\x0fIncomingPayment\x12/\n\x08offchain\x18\x01 \x01(\x0b\x32\x1b.greenlight.OffChainPaymentH\x00\x42\t\n\x07\x64\x65tails\"\x12\n\x10StreamLogRequest\"\x18\n\x08LogEntry\x12\x0c\n\x04line\x18\x01 \x01(\t\"?\n\x10SignerStateEntry\x12\x0f\n\x07version\x18\x01 \x01(\x04\x12\x0b\n\x03key\x18\x02 \x01(\t\x12\r\n\x05value\x18\x03 \x01(\x0c\"r\n\x0ePendingRequest\x12\x0f\n\x07request\x18\x01 \x01(\x0c\x12\x0b\n\x03uri\x18\x02 \x01(\t\x12\x11\n\tsignature\x18\x03 \x01(\x0c\x12\x0e\n\x06pubkey\x18\x04 \x01(\x0c\x12\x11\n\ttimestamp\x18\x05 \x01(\x04\x12\x0c\n\x04rune\x18\x06 \x01(\x0c\"=\n\nNodeConfig\x12/\n\x0bstartupmsgs\x18\x01 \x03(\x0b\x32\x1a.greenlight.StartupMessage\"!\n\x08GlConfig\x12\x15\n\rclose_to_addr\x18\x01 \x01(\t\"3\n\x0eStartupMessage\x12\x0f\n\x07request\x18\x01 \x01(\x0c\x12\x10\n\x08response\x18\x02 \x01(\x0c\"\x18\n\x16StreamCustommsgRequest\"-\n\tCustommsg\x12\x0f\n\x07peer_id\x18\x01 \x01(\x0c\x12\x0f\n\x07payload\x18\x02 \x01(\x0c\"\xa4\x01\n\x14TrampolinePayRequest\x12\x0e\n\x06\x62olt11\x18\x01 \x01(\t\x12\x1a\n\x12trampoline_node_id\x18\x02 \x01(\x0c\x12\x13\n\x0b\x61mount_msat\x18\x03 \x01(\x04\x12\r\n\x05label\x18\x04 \x01(\t\x12\x15\n\rmaxfeepercent\x18\x05 \x01(\x02\x12\x10\n\x08maxdelay\x18\x06 \x01(\r\x12\x13\n\x0b\x64\x65scription\x18\x07 \x01(\t\"\xd5\x01\n\x15TrampolinePayResponse\x12\x18\n\x10payment_preimage\x18\x01 \x01(\x0c\x12\x14\n\x0cpayment_hash\x18\x02 \x01(\x0c\x12\x12\n\ncreated_at\x18\x03 \x01(\x01\x12\r\n\x05parts\x18\x04 \x01(\r\x12\x13\n\x0b\x61mount_msat\x18\x05 \x01(\x04\x12\x18\n\x10\x61mount_sent_msat\x18\x06 \x01(\x04\x12\x13\n\x0b\x64\x65stination\x18\x07 \x01(\x0c\"%\n\tPayStatus\x12\x0c\n\x08\x43OMPLETE\x10\x00\x12\n\n\x06\x46\x41ILED\x10\x02\"k\n\x11LspInvoiceRequest\x12\x0e\n\x06lsp_id\x18\x01 \x01(\t\x12\r\n\x05token\x18\x02 \x01(\t\x12\x13\n\x0b\x61mount_msat\x18\x03 \x01(\x04\x12\x13\n\x0b\x64\x65scription\x18\x04 \x01(\t\x12\r\n\x05label\x18\x05 \x01(\t\"}\n\x12LspInvoiceResponse\x12\x0e\n\x06\x62olt11\x18\x01 \x01(\t\x12\x15\n\rcreated_index\x18\x02 \x01(\r\x12\x12\n\nexpires_at\x18\x03 \x01(\r\x12\x14\n\x0cpayment_hash\x18\x04 \x01(\x0c\x12\x16\n\x0epayment_secret\x18\x05 \x01(\x0c\"\x13\n\x11NodeEventsRequest\"E\n\tNodeEvent\x12/\n\x0cinvoice_paid\x18\x01 \x01(\x0b\x32\x17.greenlight.InvoicePaidH\x00\x42\x07\n\x05\x65vent\"\x92\x01\n\x0bInvoicePaid\x12\x14\n\x0cpayment_hash\x18\x01 \x01(\x0c\x12\x0e\n\x06\x62olt11\x18\x02 \x01(\t\x12\x10\n\x08preimage\x18\x03 \x01(\x0c\x12\r\n\x05label\x18\x04 \x01(\t\x12\x13\n\x0b\x61mount_msat\x18\x05 \x01(\x04\x12\'\n\textratlvs\x18\x06 \x03(\x0b\x32\x14.greenlight.TlvField2\xd1\x04\n\x04Node\x12M\n\nLspInvoice\x12\x1d.greenlight.LspInvoiceRequest\x1a\x1e.greenlight.LspInvoiceResponse\"\x00\x12\x43\n\tStreamLog\x12\x1c.greenlight.StreamLogRequest\x1a\x14.greenlight.LogEntry\"\x00\x30\x01\x12P\n\x0fStreamCustommsg\x12\".greenlight.StreamCustommsgRequest\x1a\x15.greenlight.Custommsg\"\x00\x30\x01\x12L\n\x10StreamNodeEvents\x12\x1d.greenlight.NodeEventsRequest\x1a\x15.greenlight.NodeEvent\"\x00\x30\x01\x12\x42\n\x11StreamHsmRequests\x12\x11.greenlight.Empty\x1a\x16.greenlight.HsmRequest\"\x00\x30\x01\x12\x41\n\x11RespondHsmRequest\x12\x17.greenlight.HsmResponse\x1a\x11.greenlight.Empty\"\x00\x12\x36\n\tConfigure\x12\x14.greenlight.GlConfig\x1a\x11.greenlight.Empty\"\x00\x12V\n\rTrampolinePay\x12 .greenlight.TrampolinePayRequest\x1a!.greenlight.TrampolinePayResponse\"\x00\x32s\n\x03Hsm\x12<\n\x07Request\x12\x16.greenlight.HsmRequest\x1a\x17.greenlight.HsmResponse\"\x00\x12.\n\x04Ping\x12\x11.greenlight.Empty\x1a\x11.greenlight.Empty\"\x00\x62\x06proto3') _globals = globals() _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) @@ -41,44 +41,48 @@ _globals['_EMPTY']._serialized_end=431 _globals['_AMOUNT']._serialized_start=433 _globals['_AMOUNT']._serialized_end=541 - _globals['_STREAMINCOMINGFILTER']._serialized_start=543 - _globals['_STREAMINCOMINGFILTER']._serialized_end=565 - _globals['_TLVFIELD']._serialized_start=567 - _globals['_TLVFIELD']._serialized_end=606 - _globals['_OFFCHAINPAYMENT']._serialized_start=609 - _globals['_OFFCHAINPAYMENT']._serialized_end=774 - _globals['_INCOMINGPAYMENT']._serialized_start=776 - _globals['_INCOMINGPAYMENT']._serialized_end=853 - _globals['_STREAMLOGREQUEST']._serialized_start=855 - _globals['_STREAMLOGREQUEST']._serialized_end=873 - _globals['_LOGENTRY']._serialized_start=875 - _globals['_LOGENTRY']._serialized_end=899 - _globals['_SIGNERSTATEENTRY']._serialized_start=901 - _globals['_SIGNERSTATEENTRY']._serialized_end=964 - _globals['_PENDINGREQUEST']._serialized_start=966 - _globals['_PENDINGREQUEST']._serialized_end=1080 - _globals['_NODECONFIG']._serialized_start=1082 - _globals['_NODECONFIG']._serialized_end=1143 - _globals['_GLCONFIG']._serialized_start=1145 - _globals['_GLCONFIG']._serialized_end=1178 - _globals['_STARTUPMESSAGE']._serialized_start=1180 - _globals['_STARTUPMESSAGE']._serialized_end=1231 - _globals['_STREAMCUSTOMMSGREQUEST']._serialized_start=1233 - _globals['_STREAMCUSTOMMSGREQUEST']._serialized_end=1257 - _globals['_CUSTOMMSG']._serialized_start=1259 - _globals['_CUSTOMMSG']._serialized_end=1304 - _globals['_TRAMPOLINEPAYREQUEST']._serialized_start=1307 - _globals['_TRAMPOLINEPAYREQUEST']._serialized_end=1471 - _globals['_TRAMPOLINEPAYRESPONSE']._serialized_start=1474 - _globals['_TRAMPOLINEPAYRESPONSE']._serialized_end=1687 - _globals['_TRAMPOLINEPAYRESPONSE_PAYSTATUS']._serialized_start=1650 - _globals['_TRAMPOLINEPAYRESPONSE_PAYSTATUS']._serialized_end=1687 - _globals['_LSPINVOICEREQUEST']._serialized_start=1689 - _globals['_LSPINVOICEREQUEST']._serialized_end=1796 - _globals['_LSPINVOICERESPONSE']._serialized_start=1798 - _globals['_LSPINVOICERESPONSE']._serialized_end=1923 - _globals['_NODE']._serialized_start=1926 - _globals['_NODE']._serialized_end=2526 - _globals['_HSM']._serialized_start=2528 - _globals['_HSM']._serialized_end=2643 + _globals['_TLVFIELD']._serialized_start=543 + _globals['_TLVFIELD']._serialized_end=582 + _globals['_OFFCHAINPAYMENT']._serialized_start=585 + _globals['_OFFCHAINPAYMENT']._serialized_end=750 + _globals['_INCOMINGPAYMENT']._serialized_start=752 + _globals['_INCOMINGPAYMENT']._serialized_end=829 + _globals['_STREAMLOGREQUEST']._serialized_start=831 + _globals['_STREAMLOGREQUEST']._serialized_end=849 + _globals['_LOGENTRY']._serialized_start=851 + _globals['_LOGENTRY']._serialized_end=875 + _globals['_SIGNERSTATEENTRY']._serialized_start=877 + _globals['_SIGNERSTATEENTRY']._serialized_end=940 + _globals['_PENDINGREQUEST']._serialized_start=942 + _globals['_PENDINGREQUEST']._serialized_end=1056 + _globals['_NODECONFIG']._serialized_start=1058 + _globals['_NODECONFIG']._serialized_end=1119 + _globals['_GLCONFIG']._serialized_start=1121 + _globals['_GLCONFIG']._serialized_end=1154 + _globals['_STARTUPMESSAGE']._serialized_start=1156 + _globals['_STARTUPMESSAGE']._serialized_end=1207 + _globals['_STREAMCUSTOMMSGREQUEST']._serialized_start=1209 + _globals['_STREAMCUSTOMMSGREQUEST']._serialized_end=1233 + _globals['_CUSTOMMSG']._serialized_start=1235 + _globals['_CUSTOMMSG']._serialized_end=1280 + _globals['_TRAMPOLINEPAYREQUEST']._serialized_start=1283 + _globals['_TRAMPOLINEPAYREQUEST']._serialized_end=1447 + _globals['_TRAMPOLINEPAYRESPONSE']._serialized_start=1450 + _globals['_TRAMPOLINEPAYRESPONSE']._serialized_end=1663 + _globals['_TRAMPOLINEPAYRESPONSE_PAYSTATUS']._serialized_start=1626 + _globals['_TRAMPOLINEPAYRESPONSE_PAYSTATUS']._serialized_end=1663 + _globals['_LSPINVOICEREQUEST']._serialized_start=1665 + _globals['_LSPINVOICEREQUEST']._serialized_end=1772 + _globals['_LSPINVOICERESPONSE']._serialized_start=1774 + _globals['_LSPINVOICERESPONSE']._serialized_end=1899 + _globals['_NODEEVENTSREQUEST']._serialized_start=1901 + _globals['_NODEEVENTSREQUEST']._serialized_end=1920 + _globals['_NODEEVENT']._serialized_start=1922 + _globals['_NODEEVENT']._serialized_end=1991 + _globals['_INVOICEPAID']._serialized_start=1994 + _globals['_INVOICEPAID']._serialized_end=2140 + _globals['_NODE']._serialized_start=2143 + _globals['_NODE']._serialized_end=2736 + _globals['_HSM']._serialized_start=2738 + _globals['_HSM']._serialized_end=2853 # @@protoc_insertion_point(module_scope) diff --git a/libs/gl-client-py/glclient/greenlight_pb2.pyi b/libs/gl-client-py/glclient/greenlight_pb2.pyi index 78426c3f3..0c58312fb 100644 --- a/libs/gl-client-py/glclient/greenlight_pb2.pyi +++ b/libs/gl-client-py/glclient/greenlight_pb2.pyi @@ -3,61 +3,62 @@ isort:skip_file """ -import builtins -import collections.abc -import google.protobuf.descriptor -import google.protobuf.internal.containers -import google.protobuf.internal.enum_type_wrapper -import google.protobuf.message +from collections import abc as _abc +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from google.protobuf.internal import containers as _containers +from google.protobuf.internal import enum_type_wrapper as _enum_type_wrapper +import builtins as _builtins import sys -import typing +import typing as _typing if sys.version_info >= (3, 10): - import typing as typing_extensions + from typing import TypeAlias as _TypeAlias else: - import typing_extensions + from typing_extensions import TypeAlias as _TypeAlias -DESCRIPTOR: google.protobuf.descriptor.FileDescriptor +DESCRIPTOR: _descriptor.FileDescriptor -@typing.final -class HsmRequestContext(google.protobuf.message.Message): - DESCRIPTOR: google.protobuf.descriptor.Descriptor +@_typing.final +class HsmRequestContext(_message.Message): + DESCRIPTOR: _descriptor.Descriptor - NODE_ID_FIELD_NUMBER: builtins.int - DBID_FIELD_NUMBER: builtins.int - CAPABILITIES_FIELD_NUMBER: builtins.int - node_id: builtins.bytes - dbid: builtins.int - capabilities: builtins.int + NODE_ID_FIELD_NUMBER: _builtins.int + DBID_FIELD_NUMBER: _builtins.int + CAPABILITIES_FIELD_NUMBER: _builtins.int + node_id: _builtins.bytes + dbid: _builtins.int + capabilities: _builtins.int def __init__( self, *, - node_id: builtins.bytes = ..., - dbid: builtins.int = ..., - capabilities: builtins.int = ..., + node_id: _builtins.bytes = ..., + dbid: _builtins.int = ..., + capabilities: _builtins.int = ..., ) -> None: ... - def ClearField(self, field_name: typing.Literal["capabilities", b"capabilities", "dbid", b"dbid", "node_id", b"node_id"]) -> None: ... - -global___HsmRequestContext = HsmRequestContext - -@typing.final -class HsmResponse(google.protobuf.message.Message): - DESCRIPTOR: google.protobuf.descriptor.Descriptor - - REQUEST_ID_FIELD_NUMBER: builtins.int - RAW_FIELD_NUMBER: builtins.int - SIGNER_STATE_FIELD_NUMBER: builtins.int - ERROR_FIELD_NUMBER: builtins.int - request_id: builtins.int - raw: builtins.bytes - error: builtins.str + _ClearFieldArgType: _TypeAlias = _typing.Literal["capabilities", b"capabilities", "dbid", b"dbid", "node_id", b"node_id"] # noqa: Y015 + def ClearField(self, field_name: _ClearFieldArgType) -> None: ... + +Global___HsmRequestContext: _TypeAlias = HsmRequestContext # noqa: Y015 + +@_typing.final +class HsmResponse(_message.Message): + DESCRIPTOR: _descriptor.Descriptor + + REQUEST_ID_FIELD_NUMBER: _builtins.int + RAW_FIELD_NUMBER: _builtins.int + SIGNER_STATE_FIELD_NUMBER: _builtins.int + ERROR_FIELD_NUMBER: _builtins.int + request_id: _builtins.int + raw: _builtins.bytes + error: _builtins.str """If the signer reported an error, and did therefore not include `raw`, this is the stringified error, so we can print it in the logs. This should help us collate policy errors with the changes proposed by CLN """ - @property - def signer_state(self) -> google.protobuf.internal.containers.RepeatedCompositeFieldContainer[global___SignerStateEntry]: + @_builtins.property + def signer_state(self) -> _containers.RepeatedCompositeFieldContainer[Global___SignerStateEntry]: """A list of updated key-value-version tuples that is to be merged into the state tracked by the plugin. """ @@ -65,36 +66,37 @@ class HsmResponse(google.protobuf.message.Message): def __init__( self, *, - request_id: builtins.int = ..., - raw: builtins.bytes = ..., - signer_state: collections.abc.Iterable[global___SignerStateEntry] | None = ..., - error: builtins.str = ..., + request_id: _builtins.int = ..., + raw: _builtins.bytes = ..., + signer_state: _abc.Iterable[Global___SignerStateEntry] | None = ..., + error: _builtins.str = ..., ) -> None: ... - def ClearField(self, field_name: typing.Literal["error", b"error", "raw", b"raw", "request_id", b"request_id", "signer_state", b"signer_state"]) -> None: ... - -global___HsmResponse = HsmResponse - -@typing.final -class HsmRequest(google.protobuf.message.Message): - DESCRIPTOR: google.protobuf.descriptor.Descriptor - - REQUEST_ID_FIELD_NUMBER: builtins.int - CONTEXT_FIELD_NUMBER: builtins.int - RAW_FIELD_NUMBER: builtins.int - SIGNER_STATE_FIELD_NUMBER: builtins.int - REQUESTS_FIELD_NUMBER: builtins.int - request_id: builtins.int - raw: builtins.bytes - @property - def context(self) -> global___HsmRequestContext: ... - @property - def signer_state(self) -> google.protobuf.internal.containers.RepeatedCompositeFieldContainer[global___SignerStateEntry]: + _ClearFieldArgType: _TypeAlias = _typing.Literal["error", b"error", "raw", b"raw", "request_id", b"request_id", "signer_state", b"signer_state"] # noqa: Y015 + def ClearField(self, field_name: _ClearFieldArgType) -> None: ... + +Global___HsmResponse: _TypeAlias = HsmResponse # noqa: Y015 + +@_typing.final +class HsmRequest(_message.Message): + DESCRIPTOR: _descriptor.Descriptor + + REQUEST_ID_FIELD_NUMBER: _builtins.int + CONTEXT_FIELD_NUMBER: _builtins.int + RAW_FIELD_NUMBER: _builtins.int + SIGNER_STATE_FIELD_NUMBER: _builtins.int + REQUESTS_FIELD_NUMBER: _builtins.int + request_id: _builtins.int + raw: _builtins.bytes + @_builtins.property + def context(self) -> Global___HsmRequestContext: ... + @_builtins.property + def signer_state(self) -> _containers.RepeatedCompositeFieldContainer[Global___SignerStateEntry]: """A list of key-value-version tuples that the signer should use to update its internal state. """ - @property - def requests(self) -> google.protobuf.internal.containers.RepeatedCompositeFieldContainer[global___PendingRequest]: + @_builtins.property + def requests(self) -> _containers.RepeatedCompositeFieldContainer[Global___PendingRequest]: """Currently active requests that are used to justify changes in state. """ @@ -102,188 +104,191 @@ class HsmRequest(google.protobuf.message.Message): def __init__( self, *, - request_id: builtins.int = ..., - context: global___HsmRequestContext | None = ..., - raw: builtins.bytes = ..., - signer_state: collections.abc.Iterable[global___SignerStateEntry] | None = ..., - requests: collections.abc.Iterable[global___PendingRequest] | None = ..., + request_id: _builtins.int = ..., + context: Global___HsmRequestContext | None = ..., + raw: _builtins.bytes = ..., + signer_state: _abc.Iterable[Global___SignerStateEntry] | None = ..., + requests: _abc.Iterable[Global___PendingRequest] | None = ..., ) -> None: ... - def HasField(self, field_name: typing.Literal["context", b"context"]) -> builtins.bool: ... - def ClearField(self, field_name: typing.Literal["context", b"context", "raw", b"raw", "request_id", b"request_id", "requests", b"requests", "signer_state", b"signer_state"]) -> None: ... + _HasFieldArgType: _TypeAlias = _typing.Literal["context", b"context"] # noqa: Y015 + def HasField(self, field_name: _HasFieldArgType) -> _builtins.bool: ... + _ClearFieldArgType: _TypeAlias = _typing.Literal["context", b"context", "raw", b"raw", "request_id", b"request_id", "requests", b"requests", "signer_state", b"signer_state"] # noqa: Y015 + def ClearField(self, field_name: _ClearFieldArgType) -> None: ... -global___HsmRequest = HsmRequest +Global___HsmRequest: _TypeAlias = HsmRequest # noqa: Y015 -@typing.final -class Empty(google.protobuf.message.Message): - DESCRIPTOR: google.protobuf.descriptor.Descriptor +@_typing.final +class Empty(_message.Message): + DESCRIPTOR: _descriptor.Descriptor def __init__( self, ) -> None: ... -global___Empty = Empty - -@typing.final -class Amount(google.protobuf.message.Message): - DESCRIPTOR: google.protobuf.descriptor.Descriptor - - MILLISATOSHI_FIELD_NUMBER: builtins.int - SATOSHI_FIELD_NUMBER: builtins.int - BITCOIN_FIELD_NUMBER: builtins.int - ALL_FIELD_NUMBER: builtins.int - ANY_FIELD_NUMBER: builtins.int - millisatoshi: builtins.int - satoshi: builtins.int - bitcoin: builtins.int - all: builtins.bool - any: builtins.bool +Global___Empty: _TypeAlias = Empty # noqa: Y015 + +@_typing.final +class Amount(_message.Message): + DESCRIPTOR: _descriptor.Descriptor + + MILLISATOSHI_FIELD_NUMBER: _builtins.int + SATOSHI_FIELD_NUMBER: _builtins.int + BITCOIN_FIELD_NUMBER: _builtins.int + ALL_FIELD_NUMBER: _builtins.int + ANY_FIELD_NUMBER: _builtins.int + millisatoshi: _builtins.int + satoshi: _builtins.int + bitcoin: _builtins.int + all: _builtins.bool + any: _builtins.bool def __init__( self, *, - millisatoshi: builtins.int = ..., - satoshi: builtins.int = ..., - bitcoin: builtins.int = ..., - all: builtins.bool = ..., - any: builtins.bool = ..., - ) -> None: ... - def HasField(self, field_name: typing.Literal["all", b"all", "any", b"any", "bitcoin", b"bitcoin", "millisatoshi", b"millisatoshi", "satoshi", b"satoshi", "unit", b"unit"]) -> builtins.bool: ... - def ClearField(self, field_name: typing.Literal["all", b"all", "any", b"any", "bitcoin", b"bitcoin", "millisatoshi", b"millisatoshi", "satoshi", b"satoshi", "unit", b"unit"]) -> None: ... - def WhichOneof(self, oneof_group: typing.Literal["unit", b"unit"]) -> typing.Literal["millisatoshi", "satoshi", "bitcoin", "all", "any"] | None: ... - -global___Amount = Amount - -@typing.final -class StreamIncomingFilter(google.protobuf.message.Message): - """Options to stream_incoming to specify what to stream.""" - - DESCRIPTOR: google.protobuf.descriptor.Descriptor - - def __init__( - self, + millisatoshi: _builtins.int = ..., + satoshi: _builtins.int = ..., + bitcoin: _builtins.int = ..., + all: _builtins.bool = ..., + any: _builtins.bool = ..., ) -> None: ... - -global___StreamIncomingFilter = StreamIncomingFilter - -@typing.final -class TlvField(google.protobuf.message.Message): - DESCRIPTOR: google.protobuf.descriptor.Descriptor - - TYPE_FIELD_NUMBER: builtins.int - VALUE_FIELD_NUMBER: builtins.int - type: builtins.int - value: builtins.bytes + _HasFieldArgType: _TypeAlias = _typing.Literal["all", b"all", "any", b"any", "bitcoin", b"bitcoin", "millisatoshi", b"millisatoshi", "satoshi", b"satoshi", "unit", b"unit"] # noqa: Y015 + def HasField(self, field_name: _HasFieldArgType) -> _builtins.bool: ... + _ClearFieldArgType: _TypeAlias = _typing.Literal["all", b"all", "any", b"any", "bitcoin", b"bitcoin", "millisatoshi", b"millisatoshi", "satoshi", b"satoshi", "unit", b"unit"] # noqa: Y015 + def ClearField(self, field_name: _ClearFieldArgType) -> None: ... + _WhichOneofReturnType_unit: _TypeAlias = _typing.Literal["millisatoshi", "satoshi", "bitcoin", "all", "any"] # noqa: Y015 + _WhichOneofArgType_unit: _TypeAlias = _typing.Literal["unit", b"unit"] # noqa: Y015 + def WhichOneof(self, oneof_group: _WhichOneofArgType_unit) -> _WhichOneofReturnType_unit | None: ... + +Global___Amount: _TypeAlias = Amount # noqa: Y015 + +@_typing.final +class TlvField(_message.Message): + DESCRIPTOR: _descriptor.Descriptor + + TYPE_FIELD_NUMBER: _builtins.int + VALUE_FIELD_NUMBER: _builtins.int + type: _builtins.int + value: _builtins.bytes """length is implied since the value field carries its own length here. """ def __init__( self, *, - type: builtins.int = ..., - value: builtins.bytes = ..., + type: _builtins.int = ..., + value: _builtins.bytes = ..., ) -> None: ... - def ClearField(self, field_name: typing.Literal["type", b"type", "value", b"value"]) -> None: ... - -global___TlvField = TlvField - -@typing.final -class OffChainPayment(google.protobuf.message.Message): - DESCRIPTOR: google.protobuf.descriptor.Descriptor - - LABEL_FIELD_NUMBER: builtins.int - PREIMAGE_FIELD_NUMBER: builtins.int - AMOUNT_FIELD_NUMBER: builtins.int - EXTRATLVS_FIELD_NUMBER: builtins.int - PAYMENT_HASH_FIELD_NUMBER: builtins.int - BOLT11_FIELD_NUMBER: builtins.int - label: builtins.str - preimage: builtins.bytes - payment_hash: builtins.bytes - bolt11: builtins.str - @property - def amount(self) -> global___Amount: ... - @property - def extratlvs(self) -> google.protobuf.internal.containers.RepeatedCompositeFieldContainer[global___TlvField]: ... + _ClearFieldArgType: _TypeAlias = _typing.Literal["type", b"type", "value", b"value"] # noqa: Y015 + def ClearField(self, field_name: _ClearFieldArgType) -> None: ... + +Global___TlvField: _TypeAlias = TlvField # noqa: Y015 + +@_typing.final +class OffChainPayment(_message.Message): + DESCRIPTOR: _descriptor.Descriptor + + LABEL_FIELD_NUMBER: _builtins.int + PREIMAGE_FIELD_NUMBER: _builtins.int + AMOUNT_FIELD_NUMBER: _builtins.int + EXTRATLVS_FIELD_NUMBER: _builtins.int + PAYMENT_HASH_FIELD_NUMBER: _builtins.int + BOLT11_FIELD_NUMBER: _builtins.int + label: _builtins.str + preimage: _builtins.bytes + payment_hash: _builtins.bytes + bolt11: _builtins.str + @_builtins.property + def amount(self) -> Global___Amount: ... + @_builtins.property + def extratlvs(self) -> _containers.RepeatedCompositeFieldContainer[Global___TlvField]: ... def __init__( self, *, - label: builtins.str = ..., - preimage: builtins.bytes = ..., - amount: global___Amount | None = ..., - extratlvs: collections.abc.Iterable[global___TlvField] | None = ..., - payment_hash: builtins.bytes = ..., - bolt11: builtins.str = ..., + label: _builtins.str = ..., + preimage: _builtins.bytes = ..., + amount: Global___Amount | None = ..., + extratlvs: _abc.Iterable[Global___TlvField] | None = ..., + payment_hash: _builtins.bytes = ..., + bolt11: _builtins.str = ..., ) -> None: ... - def HasField(self, field_name: typing.Literal["amount", b"amount"]) -> builtins.bool: ... - def ClearField(self, field_name: typing.Literal["amount", b"amount", "bolt11", b"bolt11", "extratlvs", b"extratlvs", "label", b"label", "payment_hash", b"payment_hash", "preimage", b"preimage"]) -> None: ... + _HasFieldArgType: _TypeAlias = _typing.Literal["amount", b"amount"] # noqa: Y015 + def HasField(self, field_name: _HasFieldArgType) -> _builtins.bool: ... + _ClearFieldArgType: _TypeAlias = _typing.Literal["amount", b"amount", "bolt11", b"bolt11", "extratlvs", b"extratlvs", "label", b"label", "payment_hash", b"payment_hash", "preimage", b"preimage"] # noqa: Y015 + def ClearField(self, field_name: _ClearFieldArgType) -> None: ... -global___OffChainPayment = OffChainPayment +Global___OffChainPayment: _TypeAlias = OffChainPayment # noqa: Y015 -@typing.final -class IncomingPayment(google.protobuf.message.Message): - DESCRIPTOR: google.protobuf.descriptor.Descriptor +@_typing.final +class IncomingPayment(_message.Message): + DESCRIPTOR: _descriptor.Descriptor - OFFCHAIN_FIELD_NUMBER: builtins.int - @property - def offchain(self) -> global___OffChainPayment: ... + OFFCHAIN_FIELD_NUMBER: _builtins.int + @_builtins.property + def offchain(self) -> Global___OffChainPayment: ... def __init__( self, *, - offchain: global___OffChainPayment | None = ..., + offchain: Global___OffChainPayment | None = ..., ) -> None: ... - def HasField(self, field_name: typing.Literal["details", b"details", "offchain", b"offchain"]) -> builtins.bool: ... - def ClearField(self, field_name: typing.Literal["details", b"details", "offchain", b"offchain"]) -> None: ... - def WhichOneof(self, oneof_group: typing.Literal["details", b"details"]) -> typing.Literal["offchain"] | None: ... + _HasFieldArgType: _TypeAlias = _typing.Literal["details", b"details", "offchain", b"offchain"] # noqa: Y015 + def HasField(self, field_name: _HasFieldArgType) -> _builtins.bool: ... + _ClearFieldArgType: _TypeAlias = _typing.Literal["details", b"details", "offchain", b"offchain"] # noqa: Y015 + def ClearField(self, field_name: _ClearFieldArgType) -> None: ... + _WhichOneofReturnType_details: _TypeAlias = _typing.Literal["offchain"] # noqa: Y015 + _WhichOneofArgType_details: _TypeAlias = _typing.Literal["details", b"details"] # noqa: Y015 + def WhichOneof(self, oneof_group: _WhichOneofArgType_details) -> _WhichOneofReturnType_details | None: ... -global___IncomingPayment = IncomingPayment +Global___IncomingPayment: _TypeAlias = IncomingPayment # noqa: Y015 -@typing.final -class StreamLogRequest(google.protobuf.message.Message): - DESCRIPTOR: google.protobuf.descriptor.Descriptor +@_typing.final +class StreamLogRequest(_message.Message): + DESCRIPTOR: _descriptor.Descriptor def __init__( self, ) -> None: ... -global___StreamLogRequest = StreamLogRequest +Global___StreamLogRequest: _TypeAlias = StreamLogRequest # noqa: Y015 -@typing.final -class LogEntry(google.protobuf.message.Message): - DESCRIPTOR: google.protobuf.descriptor.Descriptor +@_typing.final +class LogEntry(_message.Message): + DESCRIPTOR: _descriptor.Descriptor - LINE_FIELD_NUMBER: builtins.int - line: builtins.str + LINE_FIELD_NUMBER: _builtins.int + line: _builtins.str def __init__( self, *, - line: builtins.str = ..., + line: _builtins.str = ..., ) -> None: ... - def ClearField(self, field_name: typing.Literal["line", b"line"]) -> None: ... + _ClearFieldArgType: _TypeAlias = _typing.Literal["line", b"line"] # noqa: Y015 + def ClearField(self, field_name: _ClearFieldArgType) -> None: ... -global___LogEntry = LogEntry +Global___LogEntry: _TypeAlias = LogEntry # noqa: Y015 -@typing.final -class SignerStateEntry(google.protobuf.message.Message): - DESCRIPTOR: google.protobuf.descriptor.Descriptor +@_typing.final +class SignerStateEntry(_message.Message): + DESCRIPTOR: _descriptor.Descriptor - VERSION_FIELD_NUMBER: builtins.int - KEY_FIELD_NUMBER: builtins.int - VALUE_FIELD_NUMBER: builtins.int - version: builtins.int - key: builtins.str - value: builtins.bytes + VERSION_FIELD_NUMBER: _builtins.int + KEY_FIELD_NUMBER: _builtins.int + VALUE_FIELD_NUMBER: _builtins.int + version: _builtins.int + key: _builtins.str + value: _builtins.bytes def __init__( self, *, - version: builtins.int = ..., - key: builtins.str = ..., - value: builtins.bytes = ..., + version: _builtins.int = ..., + key: _builtins.str = ..., + value: _builtins.bytes = ..., ) -> None: ... - def ClearField(self, field_name: typing.Literal["key", b"key", "value", b"value", "version", b"version"]) -> None: ... + _ClearFieldArgType: _TypeAlias = _typing.Literal["key", b"key", "value", b"value", "version", b"version"] # noqa: Y015 + def ClearField(self, field_name: _ClearFieldArgType) -> None: ... -global___SignerStateEntry = SignerStateEntry +Global___SignerStateEntry: _TypeAlias = SignerStateEntry # noqa: Y015 -@typing.final -class PendingRequest(google.protobuf.message.Message): +@_typing.final +class PendingRequest(_message.Message): """This represents a grpc request that is currently pending, along with the pubkey of the client issuing the request and a matching signature. This allows the signer to verify that the state changes @@ -291,47 +296,48 @@ class PendingRequest(google.protobuf.message.Message): commands, and were not injected somewhere along the way. """ - DESCRIPTOR: google.protobuf.descriptor.Descriptor - - REQUEST_FIELD_NUMBER: builtins.int - URI_FIELD_NUMBER: builtins.int - SIGNATURE_FIELD_NUMBER: builtins.int - PUBKEY_FIELD_NUMBER: builtins.int - TIMESTAMP_FIELD_NUMBER: builtins.int - RUNE_FIELD_NUMBER: builtins.int - request: builtins.bytes - uri: builtins.str - signature: builtins.bytes - pubkey: builtins.bytes - timestamp: builtins.int - rune: builtins.bytes + DESCRIPTOR: _descriptor.Descriptor + + REQUEST_FIELD_NUMBER: _builtins.int + URI_FIELD_NUMBER: _builtins.int + SIGNATURE_FIELD_NUMBER: _builtins.int + PUBKEY_FIELD_NUMBER: _builtins.int + TIMESTAMP_FIELD_NUMBER: _builtins.int + RUNE_FIELD_NUMBER: _builtins.int + request: _builtins.bytes + uri: _builtins.str + signature: _builtins.bytes + pubkey: _builtins.bytes + timestamp: _builtins.int + rune: _builtins.bytes def __init__( self, *, - request: builtins.bytes = ..., - uri: builtins.str = ..., - signature: builtins.bytes = ..., - pubkey: builtins.bytes = ..., - timestamp: builtins.int = ..., - rune: builtins.bytes = ..., + request: _builtins.bytes = ..., + uri: _builtins.str = ..., + signature: _builtins.bytes = ..., + pubkey: _builtins.bytes = ..., + timestamp: _builtins.int = ..., + rune: _builtins.bytes = ..., ) -> None: ... - def ClearField(self, field_name: typing.Literal["pubkey", b"pubkey", "request", b"request", "rune", b"rune", "signature", b"signature", "timestamp", b"timestamp", "uri", b"uri"]) -> None: ... + _ClearFieldArgType: _TypeAlias = _typing.Literal["pubkey", b"pubkey", "request", b"request", "rune", b"rune", "signature", b"signature", "timestamp", b"timestamp", "uri", b"uri"] # noqa: Y015 + def ClearField(self, field_name: _ClearFieldArgType) -> None: ... -global___PendingRequest = PendingRequest +Global___PendingRequest: _TypeAlias = PendingRequest # noqa: Y015 -@typing.final -class NodeConfig(google.protobuf.message.Message): +@_typing.final +class NodeConfig(_message.Message): """The `NodeConfig` is used to pass startup parameters to the node. The `gl-plugin` will look for a file in its directory to load these values from. Please refer to the individual fields to learn what they do. """ - DESCRIPTOR: google.protobuf.descriptor.Descriptor + DESCRIPTOR: _descriptor.Descriptor - STARTUPMSGS_FIELD_NUMBER: builtins.int - @property - def startupmsgs(self) -> google.protobuf.internal.containers.RepeatedCompositeFieldContainer[global___StartupMessage]: + STARTUPMSGS_FIELD_NUMBER: _builtins.int + @_builtins.property + def startupmsgs(self) -> _containers.RepeatedCompositeFieldContainer[Global___StartupMessage]: """In order to start without a signer attached we need to stash a couple of canned messages that we'd otherwise ask from the signer. These are just request-response tuples @@ -341,35 +347,37 @@ class NodeConfig(google.protobuf.message.Message): def __init__( self, *, - startupmsgs: collections.abc.Iterable[global___StartupMessage] | None = ..., + startupmsgs: _abc.Iterable[Global___StartupMessage] | None = ..., ) -> None: ... - def ClearField(self, field_name: typing.Literal["startupmsgs", b"startupmsgs"]) -> None: ... + _ClearFieldArgType: _TypeAlias = _typing.Literal["startupmsgs", b"startupmsgs"] # noqa: Y015 + def ClearField(self, field_name: _ClearFieldArgType) -> None: ... -global___NodeConfig = NodeConfig +Global___NodeConfig: _TypeAlias = NodeConfig # noqa: Y015 -@typing.final -class GlConfig(google.protobuf.message.Message): +@_typing.final +class GlConfig(_message.Message): """The `GlConfig` is used to pass greenlight-specific startup parameters to the node. The `gl-plugin` will look for a serialized config object in the node's datastore to load these values from. Please refer to the individual fields to learn what they do. """ - DESCRIPTOR: google.protobuf.descriptor.Descriptor + DESCRIPTOR: _descriptor.Descriptor - CLOSE_TO_ADDR_FIELD_NUMBER: builtins.int - close_to_addr: builtins.str + CLOSE_TO_ADDR_FIELD_NUMBER: _builtins.int + close_to_addr: _builtins.str def __init__( self, *, - close_to_addr: builtins.str = ..., + close_to_addr: _builtins.str = ..., ) -> None: ... - def ClearField(self, field_name: typing.Literal["close_to_addr", b"close_to_addr"]) -> None: ... + _ClearFieldArgType: _TypeAlias = _typing.Literal["close_to_addr", b"close_to_addr"] # noqa: Y015 + def ClearField(self, field_name: _ClearFieldArgType) -> None: ... -global___GlConfig = GlConfig +Global___GlConfig: _TypeAlias = GlConfig # noqa: Y015 -@typing.final -class StartupMessage(google.protobuf.message.Message): +@_typing.final +class StartupMessage(_message.Message): """A message that we know will be requested by `lightningd` at startup, and that we stash a response to on the scheduler. This allows the scheduler to start a node without requiring the signer @@ -377,93 +385,96 @@ class StartupMessage(google.protobuf.message.Message): prefix, but without the length prefix. """ - DESCRIPTOR: google.protobuf.descriptor.Descriptor + DESCRIPTOR: _descriptor.Descriptor - REQUEST_FIELD_NUMBER: builtins.int - RESPONSE_FIELD_NUMBER: builtins.int - request: builtins.bytes - response: builtins.bytes + REQUEST_FIELD_NUMBER: _builtins.int + RESPONSE_FIELD_NUMBER: _builtins.int + request: _builtins.bytes + response: _builtins.bytes def __init__( self, *, - request: builtins.bytes = ..., - response: builtins.bytes = ..., + request: _builtins.bytes = ..., + response: _builtins.bytes = ..., ) -> None: ... - def ClearField(self, field_name: typing.Literal["request", b"request", "response", b"response"]) -> None: ... + _ClearFieldArgType: _TypeAlias = _typing.Literal["request", b"request", "response", b"response"] # noqa: Y015 + def ClearField(self, field_name: _ClearFieldArgType) -> None: ... -global___StartupMessage = StartupMessage +Global___StartupMessage: _TypeAlias = StartupMessage # noqa: Y015 -@typing.final -class StreamCustommsgRequest(google.protobuf.message.Message): - DESCRIPTOR: google.protobuf.descriptor.Descriptor +@_typing.final +class StreamCustommsgRequest(_message.Message): + DESCRIPTOR: _descriptor.Descriptor def __init__( self, ) -> None: ... -global___StreamCustommsgRequest = StreamCustommsgRequest +Global___StreamCustommsgRequest: _TypeAlias = StreamCustommsgRequest # noqa: Y015 -@typing.final -class Custommsg(google.protobuf.message.Message): - DESCRIPTOR: google.protobuf.descriptor.Descriptor +@_typing.final +class Custommsg(_message.Message): + DESCRIPTOR: _descriptor.Descriptor - PEER_ID_FIELD_NUMBER: builtins.int - PAYLOAD_FIELD_NUMBER: builtins.int - peer_id: builtins.bytes - payload: builtins.bytes + PEER_ID_FIELD_NUMBER: _builtins.int + PAYLOAD_FIELD_NUMBER: _builtins.int + peer_id: _builtins.bytes + payload: _builtins.bytes def __init__( self, *, - peer_id: builtins.bytes = ..., - payload: builtins.bytes = ..., + peer_id: _builtins.bytes = ..., + payload: _builtins.bytes = ..., ) -> None: ... - def ClearField(self, field_name: typing.Literal["payload", b"payload", "peer_id", b"peer_id"]) -> None: ... - -global___Custommsg = Custommsg - -@typing.final -class TrampolinePayRequest(google.protobuf.message.Message): - DESCRIPTOR: google.protobuf.descriptor.Descriptor - - BOLT11_FIELD_NUMBER: builtins.int - TRAMPOLINE_NODE_ID_FIELD_NUMBER: builtins.int - AMOUNT_MSAT_FIELD_NUMBER: builtins.int - LABEL_FIELD_NUMBER: builtins.int - MAXFEEPERCENT_FIELD_NUMBER: builtins.int - MAXDELAY_FIELD_NUMBER: builtins.int - DESCRIPTION_FIELD_NUMBER: builtins.int - bolt11: builtins.str - trampoline_node_id: builtins.bytes - amount_msat: builtins.int - label: builtins.str - maxfeepercent: builtins.float - maxdelay: builtins.int - description: builtins.str + _ClearFieldArgType: _TypeAlias = _typing.Literal["payload", b"payload", "peer_id", b"peer_id"] # noqa: Y015 + def ClearField(self, field_name: _ClearFieldArgType) -> None: ... + +Global___Custommsg: _TypeAlias = Custommsg # noqa: Y015 + +@_typing.final +class TrampolinePayRequest(_message.Message): + DESCRIPTOR: _descriptor.Descriptor + + BOLT11_FIELD_NUMBER: _builtins.int + TRAMPOLINE_NODE_ID_FIELD_NUMBER: _builtins.int + AMOUNT_MSAT_FIELD_NUMBER: _builtins.int + LABEL_FIELD_NUMBER: _builtins.int + MAXFEEPERCENT_FIELD_NUMBER: _builtins.int + MAXDELAY_FIELD_NUMBER: _builtins.int + DESCRIPTION_FIELD_NUMBER: _builtins.int + bolt11: _builtins.str + trampoline_node_id: _builtins.bytes + amount_msat: _builtins.int + label: _builtins.str + maxfeepercent: _builtins.float + maxdelay: _builtins.int + description: _builtins.str def __init__( self, *, - bolt11: builtins.str = ..., - trampoline_node_id: builtins.bytes = ..., - amount_msat: builtins.int = ..., - label: builtins.str = ..., - maxfeepercent: builtins.float = ..., - maxdelay: builtins.int = ..., - description: builtins.str = ..., + bolt11: _builtins.str = ..., + trampoline_node_id: _builtins.bytes = ..., + amount_msat: _builtins.int = ..., + label: _builtins.str = ..., + maxfeepercent: _builtins.float = ..., + maxdelay: _builtins.int = ..., + description: _builtins.str = ..., ) -> None: ... - def ClearField(self, field_name: typing.Literal["amount_msat", b"amount_msat", "bolt11", b"bolt11", "description", b"description", "label", b"label", "maxdelay", b"maxdelay", "maxfeepercent", b"maxfeepercent", "trampoline_node_id", b"trampoline_node_id"]) -> None: ... + _ClearFieldArgType: _TypeAlias = _typing.Literal["amount_msat", b"amount_msat", "bolt11", b"bolt11", "description", b"description", "label", b"label", "maxdelay", b"maxdelay", "maxfeepercent", b"maxfeepercent", "trampoline_node_id", b"trampoline_node_id"] # noqa: Y015 + def ClearField(self, field_name: _ClearFieldArgType) -> None: ... -global___TrampolinePayRequest = TrampolinePayRequest +Global___TrampolinePayRequest: _TypeAlias = TrampolinePayRequest # noqa: Y015 -@typing.final -class TrampolinePayResponse(google.protobuf.message.Message): - DESCRIPTOR: google.protobuf.descriptor.Descriptor +@_typing.final +class TrampolinePayResponse(_message.Message): + DESCRIPTOR: _descriptor.Descriptor class _PayStatus: - ValueType = typing.NewType("ValueType", builtins.int) - V: typing_extensions.TypeAlias = ValueType + ValueType = _typing.NewType("ValueType", _builtins.int) + V: _TypeAlias = ValueType # noqa: Y015 - class _PayStatusEnumTypeWrapper(google.protobuf.internal.enum_type_wrapper._EnumTypeWrapper[TrampolinePayResponse._PayStatus.ValueType], builtins.type): - DESCRIPTOR: google.protobuf.descriptor.EnumDescriptor + class _PayStatusEnumTypeWrapper(_enum_type_wrapper._EnumTypeWrapper[TrampolinePayResponse._PayStatus.ValueType], _builtins.type): + DESCRIPTOR: _descriptor.EnumDescriptor COMPLETE: TrampolinePayResponse._PayStatus.ValueType # 0 FAILED: TrampolinePayResponse._PayStatus.ValueType # 2 @@ -471,92 +482,184 @@ class TrampolinePayResponse(google.protobuf.message.Message): COMPLETE: TrampolinePayResponse.PayStatus.ValueType # 0 FAILED: TrampolinePayResponse.PayStatus.ValueType # 2 - PAYMENT_PREIMAGE_FIELD_NUMBER: builtins.int - PAYMENT_HASH_FIELD_NUMBER: builtins.int - CREATED_AT_FIELD_NUMBER: builtins.int - PARTS_FIELD_NUMBER: builtins.int - AMOUNT_MSAT_FIELD_NUMBER: builtins.int - AMOUNT_SENT_MSAT_FIELD_NUMBER: builtins.int - DESTINATION_FIELD_NUMBER: builtins.int - payment_preimage: builtins.bytes - payment_hash: builtins.bytes - created_at: builtins.float - parts: builtins.int - amount_msat: builtins.int - amount_sent_msat: builtins.int - destination: builtins.bytes + PAYMENT_PREIMAGE_FIELD_NUMBER: _builtins.int + PAYMENT_HASH_FIELD_NUMBER: _builtins.int + CREATED_AT_FIELD_NUMBER: _builtins.int + PARTS_FIELD_NUMBER: _builtins.int + AMOUNT_MSAT_FIELD_NUMBER: _builtins.int + AMOUNT_SENT_MSAT_FIELD_NUMBER: _builtins.int + DESTINATION_FIELD_NUMBER: _builtins.int + payment_preimage: _builtins.bytes + payment_hash: _builtins.bytes + created_at: _builtins.float + parts: _builtins.int + amount_msat: _builtins.int + amount_sent_msat: _builtins.int + destination: _builtins.bytes def __init__( self, *, - payment_preimage: builtins.bytes = ..., - payment_hash: builtins.bytes = ..., - created_at: builtins.float = ..., - parts: builtins.int = ..., - amount_msat: builtins.int = ..., - amount_sent_msat: builtins.int = ..., - destination: builtins.bytes = ..., + payment_preimage: _builtins.bytes = ..., + payment_hash: _builtins.bytes = ..., + created_at: _builtins.float = ..., + parts: _builtins.int = ..., + amount_msat: _builtins.int = ..., + amount_sent_msat: _builtins.int = ..., + destination: _builtins.bytes = ..., ) -> None: ... - def ClearField(self, field_name: typing.Literal["amount_msat", b"amount_msat", "amount_sent_msat", b"amount_sent_msat", "created_at", b"created_at", "destination", b"destination", "parts", b"parts", "payment_hash", b"payment_hash", "payment_preimage", b"payment_preimage"]) -> None: ... + _ClearFieldArgType: _TypeAlias = _typing.Literal["amount_msat", b"amount_msat", "amount_sent_msat", b"amount_sent_msat", "created_at", b"created_at", "destination", b"destination", "parts", b"parts", "payment_hash", b"payment_hash", "payment_preimage", b"payment_preimage"] # noqa: Y015 + def ClearField(self, field_name: _ClearFieldArgType) -> None: ... -global___TrampolinePayResponse = TrampolinePayResponse +Global___TrampolinePayResponse: _TypeAlias = TrampolinePayResponse # noqa: Y015 -@typing.final -class LspInvoiceRequest(google.protobuf.message.Message): - DESCRIPTOR: google.protobuf.descriptor.Descriptor +@_typing.final +class LspInvoiceRequest(_message.Message): + DESCRIPTOR: _descriptor.Descriptor - LSP_ID_FIELD_NUMBER: builtins.int - TOKEN_FIELD_NUMBER: builtins.int - AMOUNT_MSAT_FIELD_NUMBER: builtins.int - DESCRIPTION_FIELD_NUMBER: builtins.int - LABEL_FIELD_NUMBER: builtins.int - lsp_id: builtins.str + LSP_ID_FIELD_NUMBER: _builtins.int + TOKEN_FIELD_NUMBER: _builtins.int + AMOUNT_MSAT_FIELD_NUMBER: _builtins.int + DESCRIPTION_FIELD_NUMBER: _builtins.int + LABEL_FIELD_NUMBER: _builtins.int + lsp_id: _builtins.str """len=0 => None, let the server decide.""" - token: builtins.str + token: _builtins.str """Optional: for discounts/API keys len=0 => None """ - amount_msat: builtins.int + amount_msat: _builtins.int """Pass-through of cln invoice rpc params 0 => Any """ - description: builtins.str - label: builtins.str + description: _builtins.str + label: _builtins.str def __init__( self, *, - lsp_id: builtins.str = ..., - token: builtins.str = ..., - amount_msat: builtins.int = ..., - description: builtins.str = ..., - label: builtins.str = ..., + lsp_id: _builtins.str = ..., + token: _builtins.str = ..., + amount_msat: _builtins.int = ..., + description: _builtins.str = ..., + label: _builtins.str = ..., ) -> None: ... - def ClearField(self, field_name: typing.Literal["amount_msat", b"amount_msat", "description", b"description", "label", b"label", "lsp_id", b"lsp_id", "token", b"token"]) -> None: ... - -global___LspInvoiceRequest = LspInvoiceRequest - -@typing.final -class LspInvoiceResponse(google.protobuf.message.Message): - DESCRIPTOR: google.protobuf.descriptor.Descriptor - - BOLT11_FIELD_NUMBER: builtins.int - CREATED_INDEX_FIELD_NUMBER: builtins.int - EXPIRES_AT_FIELD_NUMBER: builtins.int - PAYMENT_HASH_FIELD_NUMBER: builtins.int - PAYMENT_SECRET_FIELD_NUMBER: builtins.int - bolt11: builtins.str - created_index: builtins.int - expires_at: builtins.int - payment_hash: builtins.bytes - payment_secret: builtins.bytes + _ClearFieldArgType: _TypeAlias = _typing.Literal["amount_msat", b"amount_msat", "description", b"description", "label", b"label", "lsp_id", b"lsp_id", "token", b"token"] # noqa: Y015 + def ClearField(self, field_name: _ClearFieldArgType) -> None: ... + +Global___LspInvoiceRequest: _TypeAlias = LspInvoiceRequest # noqa: Y015 + +@_typing.final +class LspInvoiceResponse(_message.Message): + DESCRIPTOR: _descriptor.Descriptor + + BOLT11_FIELD_NUMBER: _builtins.int + CREATED_INDEX_FIELD_NUMBER: _builtins.int + EXPIRES_AT_FIELD_NUMBER: _builtins.int + PAYMENT_HASH_FIELD_NUMBER: _builtins.int + PAYMENT_SECRET_FIELD_NUMBER: _builtins.int + bolt11: _builtins.str + created_index: _builtins.int + expires_at: _builtins.int + payment_hash: _builtins.bytes + payment_secret: _builtins.bytes + def __init__( + self, + *, + bolt11: _builtins.str = ..., + created_index: _builtins.int = ..., + expires_at: _builtins.int = ..., + payment_hash: _builtins.bytes = ..., + payment_secret: _builtins.bytes = ..., + ) -> None: ... + _ClearFieldArgType: _TypeAlias = _typing.Literal["bolt11", b"bolt11", "created_index", b"created_index", "expires_at", b"expires_at", "payment_hash", b"payment_hash", "payment_secret", b"payment_secret"] # noqa: Y015 + def ClearField(self, field_name: _ClearFieldArgType) -> None: ... + +Global___LspInvoiceResponse: _TypeAlias = LspInvoiceResponse # noqa: Y015 + +@_typing.final +class NodeEventsRequest(_message.Message): + """Request for streaming node events. Currently empty but defined as + its own message type to allow adding filters in the future (e.g., + filter by event type, invoice label, etc.) + """ + + DESCRIPTOR: _descriptor.Descriptor + + def __init__( + self, + ) -> None: ... + +Global___NodeEventsRequest: _TypeAlias = NodeEventsRequest # noqa: Y015 + +@_typing.final +class NodeEvent(_message.Message): + """A real-time event from the node. Uses oneof to discriminate between + different event types. + """ + + DESCRIPTOR: _descriptor.Descriptor + + INVOICE_PAID_FIELD_NUMBER: _builtins.int + @_builtins.property + def invoice_paid(self) -> Global___InvoicePaid: + """Future event types: + PeerConnected peer_connected = 2; + PeerDisconnected peer_disconnected = 3; + ChannelStateChanged channel_state_changed = 4; + BalanceChanged balance_changed = 5; + """ + + def __init__( + self, + *, + invoice_paid: Global___InvoicePaid | None = ..., + ) -> None: ... + _HasFieldArgType: _TypeAlias = _typing.Literal["event", b"event", "invoice_paid", b"invoice_paid"] # noqa: Y015 + def HasField(self, field_name: _HasFieldArgType) -> _builtins.bool: ... + _ClearFieldArgType: _TypeAlias = _typing.Literal["event", b"event", "invoice_paid", b"invoice_paid"] # noqa: Y015 + def ClearField(self, field_name: _ClearFieldArgType) -> None: ... + _WhichOneofReturnType_event: _TypeAlias = _typing.Literal["invoice_paid"] # noqa: Y015 + _WhichOneofArgType_event: _TypeAlias = _typing.Literal["event", b"event"] # noqa: Y015 + def WhichOneof(self, oneof_group: _WhichOneofArgType_event) -> _WhichOneofReturnType_event | None: ... + +Global___NodeEvent: _TypeAlias = NodeEvent # noqa: Y015 + +@_typing.final +class InvoicePaid(_message.Message): + """Event emitted when an invoice is paid.""" + + DESCRIPTOR: _descriptor.Descriptor + + PAYMENT_HASH_FIELD_NUMBER: _builtins.int + BOLT11_FIELD_NUMBER: _builtins.int + PREIMAGE_FIELD_NUMBER: _builtins.int + LABEL_FIELD_NUMBER: _builtins.int + AMOUNT_MSAT_FIELD_NUMBER: _builtins.int + EXTRATLVS_FIELD_NUMBER: _builtins.int + payment_hash: _builtins.bytes + """The payment hash of the paid invoice.""" + bolt11: _builtins.str + """The bolt11 invoice string.""" + preimage: _builtins.bytes + """The preimage that proves payment.""" + label: _builtins.str + """The label assigned to the invoice.""" + amount_msat: _builtins.int + """Amount received in millisatoshis.""" + @_builtins.property + def extratlvs(self) -> _containers.RepeatedCompositeFieldContainer[Global___TlvField]: + """Extra TLV fields included in the payment.""" + def __init__( self, *, - bolt11: builtins.str = ..., - created_index: builtins.int = ..., - expires_at: builtins.int = ..., - payment_hash: builtins.bytes = ..., - payment_secret: builtins.bytes = ..., + payment_hash: _builtins.bytes = ..., + bolt11: _builtins.str = ..., + preimage: _builtins.bytes = ..., + label: _builtins.str = ..., + amount_msat: _builtins.int = ..., + extratlvs: _abc.Iterable[Global___TlvField] | None = ..., ) -> None: ... - def ClearField(self, field_name: typing.Literal["bolt11", b"bolt11", "created_index", b"created_index", "expires_at", b"expires_at", "payment_hash", b"payment_hash", "payment_secret", b"payment_secret"]) -> None: ... + _ClearFieldArgType: _TypeAlias = _typing.Literal["amount_msat", b"amount_msat", "bolt11", b"bolt11", "extratlvs", b"extratlvs", "label", b"label", "payment_hash", b"payment_hash", "preimage", b"preimage"] # noqa: Y015 + def ClearField(self, field_name: _ClearFieldArgType) -> None: ... -global___LspInvoiceResponse = LspInvoiceResponse +Global___InvoicePaid: _TypeAlias = InvoicePaid # noqa: Y015 diff --git a/libs/gl-client-py/glclient/greenlight_pb2_grpc.py b/libs/gl-client-py/glclient/greenlight_pb2_grpc.py index 7800c6861..d53fa077a 100644 --- a/libs/gl-client-py/glclient/greenlight_pb2_grpc.py +++ b/libs/gl-client-py/glclient/greenlight_pb2_grpc.py @@ -5,7 +5,7 @@ from glclient import greenlight_pb2 as glclient_dot_greenlight__pb2 -GRPC_GENERATED_VERSION = '1.76.0' +GRPC_GENERATED_VERSION = '1.78.0' GRPC_VERSION = grpc.__version__ _version_not_supported = False @@ -54,11 +54,6 @@ def __init__(self, channel): request_serializer=glclient_dot_greenlight__pb2.LspInvoiceRequest.SerializeToString, response_deserializer=glclient_dot_greenlight__pb2.LspInvoiceResponse.FromString, _registered_method=True) - self.StreamIncoming = channel.unary_stream( - '/greenlight.Node/StreamIncoming', - request_serializer=glclient_dot_greenlight__pb2.StreamIncomingFilter.SerializeToString, - response_deserializer=glclient_dot_greenlight__pb2.IncomingPayment.FromString, - _registered_method=True) self.StreamLog = channel.unary_stream( '/greenlight.Node/StreamLog', request_serializer=glclient_dot_greenlight__pb2.StreamLogRequest.SerializeToString, @@ -69,6 +64,11 @@ def __init__(self, channel): request_serializer=glclient_dot_greenlight__pb2.StreamCustommsgRequest.SerializeToString, response_deserializer=glclient_dot_greenlight__pb2.Custommsg.FromString, _registered_method=True) + self.StreamNodeEvents = channel.unary_stream( + '/greenlight.Node/StreamNodeEvents', + request_serializer=glclient_dot_greenlight__pb2.NodeEventsRequest.SerializeToString, + response_deserializer=glclient_dot_greenlight__pb2.NodeEvent.FromString, + _registered_method=True) self.StreamHsmRequests = channel.unary_stream( '/greenlight.Node/StreamHsmRequests', request_serializer=glclient_dot_greenlight__pb2.Empty.SerializeToString, @@ -117,18 +117,13 @@ def LspInvoice(self, request, context): context.set_details('Method not implemented!') raise NotImplementedError('Method not implemented!') - def StreamIncoming(self, request, context): + def StreamLog(self, request, context): """Stream incoming payments Currently includes off-chain payments received matching an invoice or spontaneus paymens through keysend. - """ - context.set_code(grpc.StatusCode.UNIMPLEMENTED) - context.set_details('Method not implemented!') - raise NotImplementedError('Method not implemented!') - def StreamLog(self, request, context): - """Stream the logs as they are produced by the node + Stream the logs as they are produced by the node Mainly intended for debugging clients by tailing the log as they are written on the node. The logs start streaming from @@ -151,6 +146,18 @@ def StreamCustommsg(self, request, context): context.set_details('Method not implemented!') raise NotImplementedError('Method not implemented!') + def StreamNodeEvents(self, request, context): + """Stream node events in real-time. + + This is a unified event stream that delivers various node events + as they occur, including invoice updates, peer changes, channel + state changes, and balance updates. Events are not persisted and + will not be replayed if the stream is interrupted. + """ + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + def StreamHsmRequests(self, request, context): """////////////////////////////// HSM Messages //////////////////////// @@ -193,11 +200,6 @@ def add_NodeServicer_to_server(servicer, server): request_deserializer=glclient_dot_greenlight__pb2.LspInvoiceRequest.FromString, response_serializer=glclient_dot_greenlight__pb2.LspInvoiceResponse.SerializeToString, ), - 'StreamIncoming': grpc.unary_stream_rpc_method_handler( - servicer.StreamIncoming, - request_deserializer=glclient_dot_greenlight__pb2.StreamIncomingFilter.FromString, - response_serializer=glclient_dot_greenlight__pb2.IncomingPayment.SerializeToString, - ), 'StreamLog': grpc.unary_stream_rpc_method_handler( servicer.StreamLog, request_deserializer=glclient_dot_greenlight__pb2.StreamLogRequest.FromString, @@ -208,6 +210,11 @@ def add_NodeServicer_to_server(servicer, server): request_deserializer=glclient_dot_greenlight__pb2.StreamCustommsgRequest.FromString, response_serializer=glclient_dot_greenlight__pb2.Custommsg.SerializeToString, ), + 'StreamNodeEvents': grpc.unary_stream_rpc_method_handler( + servicer.StreamNodeEvents, + request_deserializer=glclient_dot_greenlight__pb2.NodeEventsRequest.FromString, + response_serializer=glclient_dot_greenlight__pb2.NodeEvent.SerializeToString, + ), 'StreamHsmRequests': grpc.unary_stream_rpc_method_handler( servicer.StreamHsmRequests, request_deserializer=glclient_dot_greenlight__pb2.Empty.FromString, @@ -282,7 +289,7 @@ def LspInvoice(request, _registered_method=True) @staticmethod - def StreamIncoming(request, + def StreamLog(request, target, options=(), channel_credentials=None, @@ -295,9 +302,9 @@ def StreamIncoming(request, return grpc.experimental.unary_stream( request, target, - '/greenlight.Node/StreamIncoming', - glclient_dot_greenlight__pb2.StreamIncomingFilter.SerializeToString, - glclient_dot_greenlight__pb2.IncomingPayment.FromString, + '/greenlight.Node/StreamLog', + glclient_dot_greenlight__pb2.StreamLogRequest.SerializeToString, + glclient_dot_greenlight__pb2.LogEntry.FromString, options, channel_credentials, insecure, @@ -309,7 +316,7 @@ def StreamIncoming(request, _registered_method=True) @staticmethod - def StreamLog(request, + def StreamCustommsg(request, target, options=(), channel_credentials=None, @@ -322,9 +329,9 @@ def StreamLog(request, return grpc.experimental.unary_stream( request, target, - '/greenlight.Node/StreamLog', - glclient_dot_greenlight__pb2.StreamLogRequest.SerializeToString, - glclient_dot_greenlight__pb2.LogEntry.FromString, + '/greenlight.Node/StreamCustommsg', + glclient_dot_greenlight__pb2.StreamCustommsgRequest.SerializeToString, + glclient_dot_greenlight__pb2.Custommsg.FromString, options, channel_credentials, insecure, @@ -336,7 +343,7 @@ def StreamLog(request, _registered_method=True) @staticmethod - def StreamCustommsg(request, + def StreamNodeEvents(request, target, options=(), channel_credentials=None, @@ -349,9 +356,9 @@ def StreamCustommsg(request, return grpc.experimental.unary_stream( request, target, - '/greenlight.Node/StreamCustommsg', - glclient_dot_greenlight__pb2.StreamCustommsgRequest.SerializeToString, - glclient_dot_greenlight__pb2.Custommsg.FromString, + '/greenlight.Node/StreamNodeEvents', + glclient_dot_greenlight__pb2.NodeEventsRequest.SerializeToString, + glclient_dot_greenlight__pb2.NodeEvent.FromString, options, channel_credentials, insecure, diff --git a/libs/gl-client-py/glclient/greenlight_pb2_grpc.pyi b/libs/gl-client-py/glclient/greenlight_pb2_grpc.pyi index 7b9dcab23..12f961281 100644 --- a/libs/gl-client-py/glclient/greenlight_pb2_grpc.pyi +++ b/libs/gl-client-py/glclient/greenlight_pb2_grpc.pyi @@ -3,20 +3,29 @@ isort:skip_file """ -import abc -import collections.abc -import glclient.greenlight_pb2 -import grpc -import grpc.aio -import typing +from collections import abc as _abc +from glclient import greenlight_pb2 as _greenlight_pb2 +from grpc import aio as _aio +import abc as _abc_1 +import grpc as _grpc +import sys +import typing as _typing -_T = typing.TypeVar("_T") +if sys.version_info >= (3, 11): + from typing import Self as _Self +else: + from typing_extensions import Self as _Self -class _MaybeAsyncIterator(collections.abc.AsyncIterator[_T], collections.abc.Iterator[_T], metaclass=abc.ABCMeta): ... +_T = _typing.TypeVar("_T") -class _ServicerContext(grpc.ServicerContext, grpc.aio.ServicerContext): # type: ignore[misc, type-arg] +class _MaybeAsyncIterator(_abc.AsyncIterator[_T], _abc.Iterator[_T], metaclass=_abc_1.ABCMeta): ... + +class _ServicerContext(_grpc.ServicerContext, _aio.ServicerContext): # type: ignore[misc, type-arg] ... +GRPC_GENERATED_VERSION: str +GRPC_VERSION: str + class NodeStub: """The node service represents your node running on greenlight's infrastructure. You can use the exposed RPC methods to interact @@ -35,30 +44,21 @@ class NodeStub: Greenlight-specific, and backported functionality. """ - def __init__(self, channel: typing.Union[grpc.Channel, grpc.aio.Channel]) -> None: ... - LspInvoice: grpc.UnaryUnaryMultiCallable[ - glclient.greenlight_pb2.LspInvoiceRequest, - glclient.greenlight_pb2.LspInvoiceResponse, - ] + @_typing.overload + def __new__(cls, channel: _grpc.Channel) -> _Self: ... + @_typing.overload + def __new__(cls, channel: _aio.Channel) -> NodeAsyncStub: ... + LspInvoice: _grpc.UnaryUnaryMultiCallable[_greenlight_pb2.LspInvoiceRequest, _greenlight_pb2.LspInvoiceResponse] """Create an invoice to request an incoming payment. Includes LSP negotiation to open a channel on-demand when needed. """ - - StreamIncoming: grpc.UnaryStreamMultiCallable[ - glclient.greenlight_pb2.StreamIncomingFilter, - glclient.greenlight_pb2.IncomingPayment, - ] + StreamLog: _grpc.UnaryStreamMultiCallable[_greenlight_pb2.StreamLogRequest, _greenlight_pb2.LogEntry] """Stream incoming payments Currently includes off-chain payments received matching an invoice or spontaneus paymens through keysend. - """ - StreamLog: grpc.UnaryStreamMultiCallable[ - glclient.greenlight_pb2.StreamLogRequest, - glclient.greenlight_pb2.LogEntry, - ] - """Stream the logs as they are produced by the node + Stream the logs as they are produced by the node Mainly intended for debugging clients by tailing the log as they are written on the node. The logs start streaming from @@ -67,21 +67,21 @@ class NodeStub: be rather large, and should not be streamed onto resource-constrained devices. """ - - StreamCustommsg: grpc.UnaryStreamMultiCallable[ - glclient.greenlight_pb2.StreamCustommsgRequest, - glclient.greenlight_pb2.Custommsg, - ] + StreamCustommsg: _grpc.UnaryStreamMultiCallable[_greenlight_pb2.StreamCustommsgRequest, _greenlight_pb2.Custommsg] """Listen for incoming `custommsg` messages from peers. The messages are forwarded as they come in, and will not be replayed if the stream is interrupted. """ + StreamNodeEvents: _grpc.UnaryStreamMultiCallable[_greenlight_pb2.NodeEventsRequest, _greenlight_pb2.NodeEvent] + """Stream node events in real-time. - StreamHsmRequests: grpc.UnaryStreamMultiCallable[ - glclient.greenlight_pb2.Empty, - glclient.greenlight_pb2.HsmRequest, - ] + This is a unified event stream that delivers various node events + as they occur, including invoice updates, peer changes, channel + state changes, and balance updates. Events are not persisted and + will not be replayed if the stream is interrupted. + """ + StreamHsmRequests: _grpc.UnaryStreamMultiCallable[_greenlight_pb2.Empty, _greenlight_pb2.HsmRequest] """////////////////////////////// HSM Messages //////////////////////// The following messages are related to communicating HSM @@ -93,23 +93,12 @@ class NodeStub: Stream requests from the node to any key device that can respond to them. """ + RespondHsmRequest: _grpc.UnaryUnaryMultiCallable[_greenlight_pb2.HsmResponse, _greenlight_pb2.Empty] + Configure: _grpc.UnaryUnaryMultiCallable[_greenlight_pb2.GlConfig, _greenlight_pb2.Empty] + TrampolinePay: _grpc.UnaryUnaryMultiCallable[_greenlight_pb2.TrampolinePayRequest, _greenlight_pb2.TrampolinePayResponse] - RespondHsmRequest: grpc.UnaryUnaryMultiCallable[ - glclient.greenlight_pb2.HsmResponse, - glclient.greenlight_pb2.Empty, - ] - - Configure: grpc.UnaryUnaryMultiCallable[ - glclient.greenlight_pb2.GlConfig, - glclient.greenlight_pb2.Empty, - ] - - TrampolinePay: grpc.UnaryUnaryMultiCallable[ - glclient.greenlight_pb2.TrampolinePayRequest, - glclient.greenlight_pb2.TrampolinePayResponse, - ] - -class NodeAsyncStub: +@_typing.type_check_only +class NodeAsyncStub(NodeStub): """The node service represents your node running on greenlight's infrastructure. You can use the exposed RPC methods to interact with your node. The URI used to connect to the node depends on @@ -127,29 +116,18 @@ class NodeAsyncStub: Greenlight-specific, and backported functionality. """ - LspInvoice: grpc.aio.UnaryUnaryMultiCallable[ - glclient.greenlight_pb2.LspInvoiceRequest, - glclient.greenlight_pb2.LspInvoiceResponse, - ] + def __init__(self, channel: _aio.Channel) -> None: ... + LspInvoice: _aio.UnaryUnaryMultiCallable[_greenlight_pb2.LspInvoiceRequest, _greenlight_pb2.LspInvoiceResponse] # type: ignore[assignment] """Create an invoice to request an incoming payment. Includes LSP negotiation to open a channel on-demand when needed. """ - - StreamIncoming: grpc.aio.UnaryStreamMultiCallable[ - glclient.greenlight_pb2.StreamIncomingFilter, - glclient.greenlight_pb2.IncomingPayment, - ] + StreamLog: _aio.UnaryStreamMultiCallable[_greenlight_pb2.StreamLogRequest, _greenlight_pb2.LogEntry] # type: ignore[assignment] """Stream incoming payments Currently includes off-chain payments received matching an invoice or spontaneus paymens through keysend. - """ - StreamLog: grpc.aio.UnaryStreamMultiCallable[ - glclient.greenlight_pb2.StreamLogRequest, - glclient.greenlight_pb2.LogEntry, - ] - """Stream the logs as they are produced by the node + Stream the logs as they are produced by the node Mainly intended for debugging clients by tailing the log as they are written on the node. The logs start streaming from @@ -158,21 +136,21 @@ class NodeAsyncStub: be rather large, and should not be streamed onto resource-constrained devices. """ - - StreamCustommsg: grpc.aio.UnaryStreamMultiCallable[ - glclient.greenlight_pb2.StreamCustommsgRequest, - glclient.greenlight_pb2.Custommsg, - ] + StreamCustommsg: _aio.UnaryStreamMultiCallable[_greenlight_pb2.StreamCustommsgRequest, _greenlight_pb2.Custommsg] # type: ignore[assignment] """Listen for incoming `custommsg` messages from peers. The messages are forwarded as they come in, and will not be replayed if the stream is interrupted. """ + StreamNodeEvents: _aio.UnaryStreamMultiCallable[_greenlight_pb2.NodeEventsRequest, _greenlight_pb2.NodeEvent] # type: ignore[assignment] + """Stream node events in real-time. - StreamHsmRequests: grpc.aio.UnaryStreamMultiCallable[ - glclient.greenlight_pb2.Empty, - glclient.greenlight_pb2.HsmRequest, - ] + This is a unified event stream that delivers various node events + as they occur, including invoice updates, peer changes, channel + state changes, and balance updates. Events are not persisted and + will not be replayed if the stream is interrupted. + """ + StreamHsmRequests: _aio.UnaryStreamMultiCallable[_greenlight_pb2.Empty, _greenlight_pb2.HsmRequest] # type: ignore[assignment] """////////////////////////////// HSM Messages //////////////////////// The following messages are related to communicating HSM @@ -184,23 +162,11 @@ class NodeAsyncStub: Stream requests from the node to any key device that can respond to them. """ + RespondHsmRequest: _aio.UnaryUnaryMultiCallable[_greenlight_pb2.HsmResponse, _greenlight_pb2.Empty] # type: ignore[assignment] + Configure: _aio.UnaryUnaryMultiCallable[_greenlight_pb2.GlConfig, _greenlight_pb2.Empty] # type: ignore[assignment] + TrampolinePay: _aio.UnaryUnaryMultiCallable[_greenlight_pb2.TrampolinePayRequest, _greenlight_pb2.TrampolinePayResponse] # type: ignore[assignment] - RespondHsmRequest: grpc.aio.UnaryUnaryMultiCallable[ - glclient.greenlight_pb2.HsmResponse, - glclient.greenlight_pb2.Empty, - ] - - Configure: grpc.aio.UnaryUnaryMultiCallable[ - glclient.greenlight_pb2.GlConfig, - glclient.greenlight_pb2.Empty, - ] - - TrampolinePay: grpc.aio.UnaryUnaryMultiCallable[ - glclient.greenlight_pb2.TrampolinePayRequest, - glclient.greenlight_pb2.TrampolinePayResponse, - ] - -class NodeServicer(metaclass=abc.ABCMeta): +class NodeServicer(metaclass=_abc_1.ABCMeta): """The node service represents your node running on greenlight's infrastructure. You can use the exposed RPC methods to interact with your node. The URI used to connect to the node depends on @@ -218,35 +184,28 @@ class NodeServicer(metaclass=abc.ABCMeta): Greenlight-specific, and backported functionality. """ - @abc.abstractmethod + @_abc_1.abstractmethod def LspInvoice( self, - request: glclient.greenlight_pb2.LspInvoiceRequest, + request: _greenlight_pb2.LspInvoiceRequest, context: _ServicerContext, - ) -> typing.Union[glclient.greenlight_pb2.LspInvoiceResponse, collections.abc.Awaitable[glclient.greenlight_pb2.LspInvoiceResponse]]: + ) -> _typing.Union[_greenlight_pb2.LspInvoiceResponse, _abc.Awaitable[_greenlight_pb2.LspInvoiceResponse]]: """Create an invoice to request an incoming payment. Includes LSP negotiation to open a channel on-demand when needed. """ - @abc.abstractmethod - def StreamIncoming( + @_abc_1.abstractmethod + def StreamLog( self, - request: glclient.greenlight_pb2.StreamIncomingFilter, + request: _greenlight_pb2.StreamLogRequest, context: _ServicerContext, - ) -> typing.Union[collections.abc.Iterator[glclient.greenlight_pb2.IncomingPayment], collections.abc.AsyncIterator[glclient.greenlight_pb2.IncomingPayment]]: + ) -> _typing.Union[_abc.Iterator[_greenlight_pb2.LogEntry], _abc.AsyncIterator[_greenlight_pb2.LogEntry]]: """Stream incoming payments Currently includes off-chain payments received matching an invoice or spontaneus paymens through keysend. - """ - @abc.abstractmethod - def StreamLog( - self, - request: glclient.greenlight_pb2.StreamLogRequest, - context: _ServicerContext, - ) -> typing.Union[collections.abc.Iterator[glclient.greenlight_pb2.LogEntry], collections.abc.AsyncIterator[glclient.greenlight_pb2.LogEntry]]: - """Stream the logs as they are produced by the node + Stream the logs as they are produced by the node Mainly intended for debugging clients by tailing the log as they are written on the node. The logs start streaming from @@ -256,24 +215,38 @@ class NodeServicer(metaclass=abc.ABCMeta): resource-constrained devices. """ - @abc.abstractmethod + @_abc_1.abstractmethod def StreamCustommsg( self, - request: glclient.greenlight_pb2.StreamCustommsgRequest, + request: _greenlight_pb2.StreamCustommsgRequest, context: _ServicerContext, - ) -> typing.Union[collections.abc.Iterator[glclient.greenlight_pb2.Custommsg], collections.abc.AsyncIterator[glclient.greenlight_pb2.Custommsg]]: + ) -> _typing.Union[_abc.Iterator[_greenlight_pb2.Custommsg], _abc.AsyncIterator[_greenlight_pb2.Custommsg]]: """Listen for incoming `custommsg` messages from peers. The messages are forwarded as they come in, and will not be replayed if the stream is interrupted. """ - @abc.abstractmethod + @_abc_1.abstractmethod + def StreamNodeEvents( + self, + request: _greenlight_pb2.NodeEventsRequest, + context: _ServicerContext, + ) -> _typing.Union[_abc.Iterator[_greenlight_pb2.NodeEvent], _abc.AsyncIterator[_greenlight_pb2.NodeEvent]]: + """Stream node events in real-time. + + This is a unified event stream that delivers various node events + as they occur, including invoice updates, peer changes, channel + state changes, and balance updates. Events are not persisted and + will not be replayed if the stream is interrupted. + """ + + @_abc_1.abstractmethod def StreamHsmRequests( self, - request: glclient.greenlight_pb2.Empty, + request: _greenlight_pb2.Empty, context: _ServicerContext, - ) -> typing.Union[collections.abc.Iterator[glclient.greenlight_pb2.HsmRequest], collections.abc.AsyncIterator[glclient.greenlight_pb2.HsmRequest]]: + ) -> _typing.Union[_abc.Iterator[_greenlight_pb2.HsmRequest], _abc.AsyncIterator[_greenlight_pb2.HsmRequest]]: """////////////////////////////// HSM Messages //////////////////////// The following messages are related to communicating HSM @@ -286,65 +259,56 @@ class NodeServicer(metaclass=abc.ABCMeta): respond to them. """ - @abc.abstractmethod + @_abc_1.abstractmethod def RespondHsmRequest( self, - request: glclient.greenlight_pb2.HsmResponse, + request: _greenlight_pb2.HsmResponse, context: _ServicerContext, - ) -> typing.Union[glclient.greenlight_pb2.Empty, collections.abc.Awaitable[glclient.greenlight_pb2.Empty]]: ... + ) -> _typing.Union[_greenlight_pb2.Empty, _abc.Awaitable[_greenlight_pb2.Empty]]: ... - @abc.abstractmethod + @_abc_1.abstractmethod def Configure( self, - request: glclient.greenlight_pb2.GlConfig, + request: _greenlight_pb2.GlConfig, context: _ServicerContext, - ) -> typing.Union[glclient.greenlight_pb2.Empty, collections.abc.Awaitable[glclient.greenlight_pb2.Empty]]: ... + ) -> _typing.Union[_greenlight_pb2.Empty, _abc.Awaitable[_greenlight_pb2.Empty]]: ... - @abc.abstractmethod + @_abc_1.abstractmethod def TrampolinePay( self, - request: glclient.greenlight_pb2.TrampolinePayRequest, + request: _greenlight_pb2.TrampolinePayRequest, context: _ServicerContext, - ) -> typing.Union[glclient.greenlight_pb2.TrampolinePayResponse, collections.abc.Awaitable[glclient.greenlight_pb2.TrampolinePayResponse]]: ... + ) -> _typing.Union[_greenlight_pb2.TrampolinePayResponse, _abc.Awaitable[_greenlight_pb2.TrampolinePayResponse]]: ... -def add_NodeServicer_to_server(servicer: NodeServicer, server: typing.Union[grpc.Server, grpc.aio.Server]) -> None: ... +def add_NodeServicer_to_server(servicer: NodeServicer, server: _typing.Union[_grpc.Server, _aio.Server]) -> None: ... class HsmStub: - def __init__(self, channel: typing.Union[grpc.Channel, grpc.aio.Channel]) -> None: ... - Request: grpc.UnaryUnaryMultiCallable[ - glclient.greenlight_pb2.HsmRequest, - glclient.greenlight_pb2.HsmResponse, - ] - - Ping: grpc.UnaryUnaryMultiCallable[ - glclient.greenlight_pb2.Empty, - glclient.greenlight_pb2.Empty, - ] - -class HsmAsyncStub: - Request: grpc.aio.UnaryUnaryMultiCallable[ - glclient.greenlight_pb2.HsmRequest, - glclient.greenlight_pb2.HsmResponse, - ] - - Ping: grpc.aio.UnaryUnaryMultiCallable[ - glclient.greenlight_pb2.Empty, - glclient.greenlight_pb2.Empty, - ] - -class HsmServicer(metaclass=abc.ABCMeta): - @abc.abstractmethod + @_typing.overload + def __new__(cls, channel: _grpc.Channel) -> _Self: ... + @_typing.overload + def __new__(cls, channel: _aio.Channel) -> HsmAsyncStub: ... + Request: _grpc.UnaryUnaryMultiCallable[_greenlight_pb2.HsmRequest, _greenlight_pb2.HsmResponse] + Ping: _grpc.UnaryUnaryMultiCallable[_greenlight_pb2.Empty, _greenlight_pb2.Empty] + +@_typing.type_check_only +class HsmAsyncStub(HsmStub): + def __init__(self, channel: _aio.Channel) -> None: ... + Request: _aio.UnaryUnaryMultiCallable[_greenlight_pb2.HsmRequest, _greenlight_pb2.HsmResponse] # type: ignore[assignment] + Ping: _aio.UnaryUnaryMultiCallable[_greenlight_pb2.Empty, _greenlight_pb2.Empty] # type: ignore[assignment] + +class HsmServicer(metaclass=_abc_1.ABCMeta): + @_abc_1.abstractmethod def Request( self, - request: glclient.greenlight_pb2.HsmRequest, + request: _greenlight_pb2.HsmRequest, context: _ServicerContext, - ) -> typing.Union[glclient.greenlight_pb2.HsmResponse, collections.abc.Awaitable[glclient.greenlight_pb2.HsmResponse]]: ... + ) -> _typing.Union[_greenlight_pb2.HsmResponse, _abc.Awaitable[_greenlight_pb2.HsmResponse]]: ... - @abc.abstractmethod + @_abc_1.abstractmethod def Ping( self, - request: glclient.greenlight_pb2.Empty, + request: _greenlight_pb2.Empty, context: _ServicerContext, - ) -> typing.Union[glclient.greenlight_pb2.Empty, collections.abc.Awaitable[glclient.greenlight_pb2.Empty]]: ... + ) -> _typing.Union[_greenlight_pb2.Empty, _abc.Awaitable[_greenlight_pb2.Empty]]: ... -def add_HsmServicer_to_server(servicer: HsmServicer, server: typing.Union[grpc.Server, grpc.aio.Server]) -> None: ... +def add_HsmServicer_to_server(servicer: HsmServicer, server: _typing.Union[_grpc.Server, _aio.Server]) -> None: ... diff --git a/libs/gl-client-py/src/node.rs b/libs/gl-client-py/src/node.rs index 992a3a491..3a94414cd 100644 --- a/libs/gl-client-py/src/node.rs +++ b/libs/gl-client-py/src/node.rs @@ -40,15 +40,6 @@ impl Node { Ok(LogStream { inner: stream }) } - fn stream_incoming(&self, args: &[u8]) -> PyResult { - let req = pb::StreamIncomingFilter::decode(args).map_err(error_decoding_request)?; - - let stream = exec(self.client.clone().stream_incoming(req)) - .map(|x| x.into_inner()) - .map_err(error_starting_stream)?; - Ok(IncomingStream { inner: stream }) - } - fn stream_custommsg(&self, args: &[u8]) -> PyResult { let req = pb::StreamCustommsgRequest::decode(args).map_err(error_decoding_request)?; let stream = exec(self.client.clone().stream_custommsg(req)) @@ -57,6 +48,14 @@ impl Node { Ok(CustommsgStream { inner: stream }) } + fn stream_node_events(&self, args: &[u8]) -> PyResult { + let req = pb::NodeEventsRequest::decode(args).map_err(error_decoding_request)?; + let stream = exec(self.client.clone().stream_node_events(req)) + .map(|x| x.into_inner()) + .map_err(error_starting_stream)?; + Ok(NodeEventStream { inner: stream }) + } + fn trampoline_pay( &self, bolt11: String, @@ -139,24 +138,24 @@ impl LogStream { } #[pyclass] -struct IncomingStream { - inner: tonic::codec::Streaming, +struct CustommsgStream { + inner: tonic::codec::Streaming, } #[pymethods] -impl IncomingStream { +impl CustommsgStream { fn next(&mut self) -> PyResult>> { convert_stream_entry(exec(async { self.inner.message().await })) } } #[pyclass] -struct CustommsgStream { - inner: tonic::codec::Streaming, +struct NodeEventStream { + inner: tonic::codec::Streaming, } #[pymethods] -impl CustommsgStream { +impl NodeEventStream { fn next(&mut self) -> PyResult>> { convert_stream_entry(exec(async { self.inner.message().await })) } diff --git a/libs/gl-client/.resources/proto/glclient/greenlight.proto b/libs/gl-client/.resources/proto/glclient/greenlight.proto index 63dd182c0..ba9528a6d 100644 --- a/libs/gl-client/.resources/proto/glclient/greenlight.proto +++ b/libs/gl-client/.resources/proto/glclient/greenlight.proto @@ -25,7 +25,6 @@ service Node { // // Currently includes off-chain payments received matching an // invoice or spontaneus paymens through keysend. - rpc StreamIncoming(StreamIncomingFilter) returns (stream IncomingPayment) {} // Stream the logs as they are produced by the node // @@ -43,6 +42,14 @@ service Node { // replayed if the stream is interrupted. rpc StreamCustommsg(StreamCustommsgRequest) returns (stream Custommsg) {} + // Stream node events in real-time. + // + // This is a unified event stream that delivers various node events + // as they occur, including invoice updates, peer changes, channel + // state changes, and balance updates. Events are not persisted and + // will not be replayed if the stream is interrupted. + rpc StreamNodeEvents(NodeEventsRequest) returns (stream NodeEvent) {} + //////////////////////////////// HSM Messages //////////////////////// // // The following messages are related to communicating HSM @@ -113,9 +120,6 @@ message Amount { } } -// Options to stream_incoming to specify what to stream. -message StreamIncomingFilter { -} message TlvField { uint64 type = 1; @@ -243,3 +247,38 @@ message LspInvoiceResponse { bytes payment_hash = 4; bytes payment_secret = 5; } + +// Request for streaming node events. Currently empty but defined as +// its own message type to allow adding filters in the future (e.g., +// filter by event type, invoice label, etc.) +message NodeEventsRequest { +} + +// A real-time event from the node. Uses oneof to discriminate between +// different event types. +message NodeEvent { + oneof event { + InvoicePaid invoice_paid = 1; + // Future event types: + // PeerConnected peer_connected = 2; + // PeerDisconnected peer_disconnected = 3; + // ChannelStateChanged channel_state_changed = 4; + // BalanceChanged balance_changed = 5; + } +} + +// Event emitted when an invoice is paid. +message InvoicePaid { + // The payment hash of the paid invoice. + bytes payment_hash = 1; + // The bolt11 invoice string. + string bolt11 = 2; + // The preimage that proves payment. + bytes preimage = 3; + // The label assigned to the invoice. + string label = 4; + // Amount received in millisatoshis. + uint64 amount_msat = 5; + // Extra TLV fields included in the payment. + repeated TlvField extratlvs = 6; +} diff --git a/libs/gl-client/Cargo.toml b/libs/gl-client/Cargo.toml index 200a8d709..9ac1254fb 100644 --- a/libs/gl-client/Cargo.toml +++ b/libs/gl-client/Cargo.toml @@ -42,7 +42,7 @@ rustls-pemfile = "1.0.4" sha256 = "1.5.0" tokio = { version = "1", features = ["full"] } tokio-stream = "0.1" -tonic = { version = "0.11", features = ["tls", "transport"] } +tonic = { workspace = true, features = ["tls", "transport"] } tower = { version = "0.4" } tempfile = "3.10.1" url = "2.5.0" diff --git a/libs/gl-plugin/.resources/proto/glclient/greenlight.proto b/libs/gl-plugin/.resources/proto/glclient/greenlight.proto index 63dd182c0..7ed7b145c 100644 --- a/libs/gl-plugin/.resources/proto/glclient/greenlight.proto +++ b/libs/gl-plugin/.resources/proto/glclient/greenlight.proto @@ -21,12 +21,6 @@ service Node { // negotiation to open a channel on-demand when needed. rpc LspInvoice(LspInvoiceRequest) returns (LspInvoiceResponse) {} - // Stream incoming payments - // - // Currently includes off-chain payments received matching an - // invoice or spontaneus paymens through keysend. - rpc StreamIncoming(StreamIncomingFilter) returns (stream IncomingPayment) {} - // Stream the logs as they are produced by the node // // Mainly intended for debugging clients by tailing the log as @@ -43,6 +37,14 @@ service Node { // replayed if the stream is interrupted. rpc StreamCustommsg(StreamCustommsgRequest) returns (stream Custommsg) {} + // Stream node events in real-time. + // + // This is a unified event stream that delivers various node events + // as they occur, including invoice updates, peer changes, channel + // state changes, and balance updates. Events are not persisted and + // will not be replayed if the stream is interrupted. + rpc StreamNodeEvents(NodeEventsRequest) returns (stream NodeEvent) {} + //////////////////////////////// HSM Messages //////////////////////// // // The following messages are related to communicating HSM @@ -113,10 +115,6 @@ message Amount { } } -// Options to stream_incoming to specify what to stream. -message StreamIncomingFilter { -} - message TlvField { uint64 type = 1; // length is implied since the value field carries its own @@ -243,3 +241,38 @@ message LspInvoiceResponse { bytes payment_hash = 4; bytes payment_secret = 5; } + +// Request for streaming node events. Currently empty but defined as +// its own message type to allow adding filters in the future (e.g., +// filter by event type, invoice label, etc.) +message NodeEventsRequest { +} + +// A real-time event from the node. Uses oneof to discriminate between +// different event types. +message NodeEvent { + oneof event { + InvoicePaid invoice_paid = 1; + // Future event types: + // PeerConnected peer_connected = 2; + // PeerDisconnected peer_disconnected = 3; + // ChannelStateChanged channel_state_changed = 4; + // BalanceChanged balance_changed = 5; + } +} + +// Event emitted when an invoice is paid. +message InvoicePaid { + // The payment hash of the paid invoice. + bytes payment_hash = 1; + // The bolt11 invoice string. + string bolt11 = 2; + // The preimage that proves payment. + bytes preimage = 3; + // The label assigned to the invoice. + string label = 4; + // Amount received in millisatoshis. + uint64 amount_msat = 5; + // Extra TLV fields included in the payment. + repeated TlvField extratlvs = 6; +} diff --git a/libs/gl-plugin/src/events.rs b/libs/gl-plugin/src/events.rs new file mode 100644 index 000000000..cd0dbeae9 --- /dev/null +++ b/libs/gl-plugin/src/events.rs @@ -0,0 +1,423 @@ +//! Event system for gl-plugin with support for internal extensions. +//! +//! This module provides a generic `Event` enum that can be extended +//! by downstream crates (like gl-plugin-internal) with custom internal +//! event types, while keeping the core events defined here. +//! +//! # Architecture +//! +//! The event system has two layers: +//! +//! - **Internal events** (`Event::Internal(I)`) - Type-erased events for +//! communication within the plugin process. Not exposed to clients. +//! - **Public events** (`Event::IncomingPayment`, etc.) - Automatically +//! converted to `NodeEvent` protobufs and streamed to gl-sdk clients +//! via `StreamNodeEvents`. +//! +//! The [`EventBus`] uses `tokio::sync::broadcast` so multiple subscribers +//! can receive the same events. Events are not persisted - if a client +//! disconnects, it won't receive missed events. +//! +//! # Examples +//! +//! In these examples, we define a type alias for the event type to avoid +//! repeating the generic parameter. This is the recommended pattern: +//! +//! ```ignore +//! use gl_plugin::events::Event; +//! +//! // In gl-plugin (no internal events): +//! type PluginEvent = Event<()>; +//! +//! // In gl-plugin-internal (with internal events): +//! #[derive(Clone, Debug)] +//! pub enum InternalPayload { +//! NodeMeta { node_id: Vec, version: String }, +//! Shutdown { reason: String }, +//! } +//! type PluginEvent = Event; +//! ``` +//! +//! ## Publishing an Internal Event +//! +//! Internal events are for communication within the plugin system and +//! are NOT exposed to clients. Use the `Internal` variant with your payload: +//! +//! ```ignore +//! use gl_plugin::events::{Event, EventBus}; +//! +//! // Define your internal payload type +//! #[derive(Clone, Debug)] +//! pub enum InternalPayload { +//! NodeMeta { node_id: Vec, version: String }, +//! Shutdown { reason: String }, +//! } +//! +//! // Define a type alias for convenience +//! type PluginEvent = Event; +//! +//! fn publish_internal_event(bus: &EventBus) { +//! let payload = InternalPayload::NodeMeta { +//! node_id: vec![0x02; 33], +//! version: "v25.12".to_string(), +//! }; +//! bus.publish(PluginEvent::Internal(payload)); +//! } +//! ``` +//! +//! ## Subscribing to Internal Events +//! +//! Use the [`ErasedEventExt`] trait to downcast internal payloads: +//! +//! ```ignore +//! use gl_plugin::events::{EventBus, ErasedEventExt}; +//! +//! async fn subscribe_to_internal_events(bus: &EventBus) { +//! let mut rx = bus.subscribe(); +//! +//! while let Ok(event) = rx.recv().await { +//! if let Some(payload) = event.downcast_internal::() { +//! match payload { +//! InternalPayload::NodeMeta { node_id, version } => { +//! println!("Node {} running {}", hex::encode(node_id), version); +//! } +//! InternalPayload::Shutdown { reason } => { +//! println!("Shutting down: {}", reason); +//! break; +//! } +//! } +//! } +//! } +//! } +//! ``` +//! +//! ## Publishing a Public Event +//! +//! Public events like `IncomingPayment` are automatically converted to +//! `NodeEvent` protobufs and streamed to clients via `StreamNodeEvents`. +//! Using the type alias, the same code works regardless of whether you +//! have internal events or not: +//! +//! ```ignore +//! use gl_plugin::events::{Event, EventBus}; +//! use gl_plugin::pb; +//! +//! // Use () if you don't need internal events, or your InternalPayload type +//! type PluginEvent = Event<()>; +//! +//! fn on_invoice_payment(bus: &EventBus, payment_hash: Vec, +//! bolt11: String, preimage: Vec, amount_msat: u64) { +//! let payment = pb::IncomingPayment { +//! details: Some(pb::incoming_payment::Details::Offchain(pb::OffChain { +//! payment_hash, +//! bolt11, +//! preimage, +//! label: "my-invoice".to_string(), +//! amount: Some(pb::Amount { +//! unit: Some(pb::amount::Unit::Millisatoshi(amount_msat)), +//! }), +//! extratlvs: vec![], +//! })), +//! }; +//! +//! // This event will be streamed to gl-sdk clients as NodeEvent::InvoicePaid +//! bus.publish(PluginEvent::IncomingPayment(payment)); +//! } +//! ``` +//! +//! ## Subscribing to Public Events (Server-side) +//! +//! When subscribing, you receive `ErasedEvent` which works with any +//! internal type. Pattern match on the public variants directly: +//! +//! ```ignore +//! use gl_plugin::events::{Event, EventBus, ErasedEvent}; +//! +//! async fn monitor_payments(bus: &EventBus) { +//! let mut rx = bus.subscribe(); +//! +//! while let Ok(event) = rx.recv().await { +//! // ErasedEvent can be matched on public variants directly +//! match &event { +//! Event::IncomingPayment(p) => { +//! println!("Payment received!"); +//! } +//! Event::CustomMsg(msg) => { +//! println!("Custom message from peer"); +//! } +//! Event::Stop(_) => { +//! println!("Plugin stopping"); +//! break; +//! } +//! Event::Internal(_) => { +//! // Use downcast_internal::() to access typed payload +//! } +//! _ => {} +//! } +//! } +//! } +//! ``` +//! +//! ## Client-side: Consuming Events via gl-sdk (Python) +//! +//! ```python +//! # Stream events from a Greenlight node +//! for event in node.stream_node_events(): +//! if event.HasField("invoice_paid"): +//! paid = event.invoice_paid +//! print(f"Invoice paid: {paid.amount_msat} msat") +//! print(f" hash: {paid.payment_hash.hex()}") +//! ``` +//! +//! ## Client-side: Consuming Events via gl-sdk (Rust) +//! +//! ```ignore +//! use gl_client::pb::{NodeEventsRequest, node_event::Event}; +//! +//! async fn stream_events(mut client: NodeClient) -> Result<()> { +//! let stream = client +//! .stream_node_events(NodeEventsRequest {}) +//! .await? +//! .into_inner(); +//! +//! while let Some(event) = stream.message().await? { +//! match event.event { +//! Some(Event::InvoicePaid(paid)) => { +//! println!("Invoice paid: {} msat", paid.amount_msat); +//! } +//! _ => {} +//! } +//! } +//! Ok(()) +//! } +//! ``` + +use crate::pb; +use crate::stager; +use std::any::Any; +use std::fmt::Debug; +use std::sync::Arc; +use tokio::sync::broadcast; + +/// An event that can be observed during the operation of the plugin. +/// +/// The type parameter `I` allows downstream crates to extend the event +/// system with internal-only event types. In gl-plugin, `I` defaults to +/// `()` (no internal events). In gl-plugin-internal, `I` is set to +/// `InternalPayload` containing events like `NodeMeta`, `Shutdown`, etc. +#[non_exhaustive] +#[derive(Clone, Debug)] +pub enum Event { + /// The plugin is stopping. + Stop(Arc), + + /// A gRPC call was made. The string is the URI of the request. + RpcCall(String), + + /// An incoming payment was received (invoice paid). + IncomingPayment(pb::IncomingPayment), + + /// A custom message was received from a peer. + CustomMsg(pb::Custommsg), + + /// Internal events from gl-plugin-internal or other extensions. + /// This variant is not used when `I = ()`. + Internal(I), +} + +impl Event { + /// Transform the internal payload type using a mapping function. + pub fn map_internal(self, f: F) -> Event + where + F: FnOnce(I) -> J, + { + match self { + Event::Stop(s) => Event::Stop(s), + Event::RpcCall(r) => Event::RpcCall(r), + Event::IncomingPayment(p) => Event::IncomingPayment(p), + Event::CustomMsg(m) => Event::CustomMsg(m), + Event::Internal(i) => Event::Internal(f(i)), + } + } + + /// Try to transform the internal payload, returning None if the + /// transformation fails. + pub fn try_map_internal(self, f: F) -> Option> + where + F: FnOnce(I) -> Option, + { + match self { + Event::Stop(s) => Some(Event::Stop(s)), + Event::RpcCall(r) => Some(Event::RpcCall(r)), + Event::IncomingPayment(p) => Some(Event::IncomingPayment(p)), + Event::CustomMsg(m) => Some(Event::CustomMsg(m)), + Event::Internal(i) => f(i).map(Event::Internal), + } + } +} + +/// Type alias for the erased internal event type used by EventBus. +/// Uses Arc for clonability required by broadcast channel. +pub type ErasedInternal = Arc; + +/// Type alias for events with type-erased internal payload. +pub type ErasedEvent = Event; + +/// An event bus that supports multiple subscribers and type-erased +/// internal events. +/// +/// The bus internally stores `Event>` to +/// allow publishing events with any internal payload type. Subscribers +/// can then downcast back to their expected type. +#[derive(Clone)] +pub struct EventBus { + sender: broadcast::Sender, +} + +impl EventBus { + /// Create a new event bus with the given capacity. + pub fn new(capacity: usize) -> Self { + let (sender, _) = broadcast::channel(capacity); + Self { sender } + } + + /// Publish an event with a typed internal payload. + /// + /// The internal payload is type-erased before being sent on the bus. + pub fn publish(&self, event: Event) + where + I: Send + Sync + 'static, + { + let erased = event.map_internal(|i| Arc::new(i) as ErasedInternal); + // Ignore error if no subscribers + let _ = self.sender.send(erased); + } + + /// Subscribe to receive all events with type-erased internal payloads. + pub fn subscribe(&self) -> broadcast::Receiver { + self.sender.subscribe() + } + + /// Get a clone of the sender for sharing across tasks. + pub fn sender(&self) -> broadcast::Sender { + self.sender.clone() + } +} + +impl Default for EventBus { + fn default() -> Self { + Self::new(16) + } +} + +/// Extension trait for working with erased events. +pub trait ErasedEventExt { + /// Try to downcast the internal payload to a specific type. + /// + /// Returns `Some(&T)` if the event is `Event::Internal` and the + /// payload can be downcast to `T`, otherwise returns `None`. + fn downcast_internal(&self) -> Option<&T>; + + /// Try to convert this erased event back to a typed event. + /// + /// Returns `Some(Event)` if the internal payload (if present) + /// can be downcast to `I`, otherwise returns `None`. + fn try_into_typed(&self) -> Option>; +} + +impl ErasedEventExt for ErasedEvent { + fn downcast_internal(&self) -> Option<&T> { + match self { + Event::Internal(any) => any.downcast_ref::(), + _ => None, + } + } + + fn try_into_typed(&self) -> Option> { + match self { + Event::Stop(s) => Some(Event::Stop(s.clone())), + Event::RpcCall(r) => Some(Event::RpcCall(r.clone())), + Event::IncomingPayment(p) => Some(Event::IncomingPayment(p.clone())), + Event::CustomMsg(m) => Some(Event::CustomMsg(m.clone())), + Event::Internal(any) => any.downcast_ref::().cloned().map(Event::Internal), + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[derive(Clone, Debug, PartialEq)] + struct TestInternal { + value: i32, + } + + #[test] + fn test_event_map_internal() { + let event: Event = Event::Internal(42); + let mapped: Event = event.map_internal(|i| i.to_string()); + match mapped { + Event::Internal(s) => assert_eq!(s, "42"), + _ => panic!("Expected Internal variant"), + } + } + + #[test] + fn test_event_map_internal_preserves_other_variants() { + let event: Event = Event::RpcCall("test".to_string()); + let mapped: Event = event.map_internal(|i| i.to_string()); + match mapped { + Event::RpcCall(s) => assert_eq!(s, "test"), + _ => panic!("Expected RpcCall variant"), + } + } + + #[tokio::test] + async fn test_event_bus_publish_subscribe() { + let bus = EventBus::new(8); + let mut rx = bus.subscribe(); + + bus.publish(Event::<()>::RpcCall("test_method".to_string())); + + let received = rx.recv().await.unwrap(); + match received { + Event::RpcCall(method) => assert_eq!(method, "test_method"), + _ => panic!("Expected RpcCall"), + } + } + + #[tokio::test] + async fn test_event_bus_with_internal_payload() { + let bus = EventBus::new(8); + let mut rx = bus.subscribe(); + + let internal = TestInternal { value: 123 }; + bus.publish(Event::Internal(internal.clone())); + + let received = rx.recv().await.unwrap(); + let downcasted = received.downcast_internal::(); + assert_eq!(downcasted, Some(&internal)); + } + + #[test] + fn test_erased_event_try_into_typed() { + let bus = EventBus::new(8); + + // Publish a typed event + let internal = TestInternal { value: 456 }; + let event = Event::Internal(internal.clone()); + let erased = event.map_internal(|i| Arc::new(i) as ErasedInternal); + + // Try to convert back + let typed: Option> = erased.try_into_typed(); + assert!(typed.is_some()); + match typed.unwrap() { + Event::Internal(t) => assert_eq!(t, internal), + _ => panic!("Expected Internal variant"), + } + + // Suppress unused variable warning + let _ = bus; + } +} diff --git a/libs/gl-plugin/src/lib.rs b/libs/gl-plugin/src/lib.rs index 04ed784f0..b940f71c4 100644 --- a/libs/gl-plugin/src/lib.rs +++ b/libs/gl-plugin/src/lib.rs @@ -11,6 +11,7 @@ extern crate gl_util; mod awaitables; pub mod config; +pub mod events; pub mod hsm; mod lsp; pub mod messages; @@ -27,6 +28,9 @@ mod unix; mod context; +// Re-export the event types for convenience and backwards compatibility +pub use events::{ErasedEvent, ErasedEventExt, ErasedInternal, Event, EventBus}; + #[derive(Clone)] pub struct GlPlugin { stage: Arc, @@ -290,15 +294,4 @@ async fn on_invoice_payment(plugin: Plugin, v: serde_json::Value) -> Result), - - /// A grpc call. The first element is the URI of the request. - RpcCall(String), - IncomingPayment(pb::IncomingPayment), - CustomMsg(pb::Custommsg), -} - pub use cln_grpc as grpc; diff --git a/libs/gl-plugin/src/node/mod.rs b/libs/gl-plugin/src/node/mod.rs index c865fb70c..70eab90f1 100644 --- a/libs/gl-plugin/src/node/mod.rs +++ b/libs/gl-plugin/src/node/mod.rs @@ -25,6 +25,7 @@ use tokio_stream::wrappers::ReceiverStream; use tonic::{transport::ServerTlsConfig, Code, Request, Response, Status}; mod wrapper; use gl_client::bitcoin; +use std::borrow::Borrow; use std::str::FromStr; pub use wrapper::WrappedNodeServer; @@ -218,7 +219,7 @@ impl Node for PluginNodeServer { ); // Create a regular invoice without JIT channel negotiation - let invreq = crate::requests::Invoice { + let invreq = cln_rpc::model::requests::InvoiceRequest { amount_msat: cln_rpc::primitives::AmountOrAny::Amount( cln_rpc::primitives::Amount::from_msat(req.amount_msat), ), @@ -230,24 +231,19 @@ impl Node for PluginNodeServer { cltv: Some(144), deschashonly: None, exposeprivatechannels: None, - dev_routes: None, }; - let res: crate::responses::Invoice = rpc - .call_raw("invoice", &invreq) + let res = rpc + .call_typed(&invreq) .await .map_err(|e| Status::new(Code::Internal, e.to_string()))?; return Ok(Response::new(pb::LspInvoiceResponse { bolt11: res.bolt11, - created_index: 0, // Not available in our Invoice response - expires_at: res.expiry_time, - payment_hash: hex::decode(&res.payment_hash) - .map_err(|e| Status::new(Code::Internal, format!("Invalid payment_hash: {}", e)))?, - payment_secret: res - .payment_secret - .map(|s| hex::decode(&s).unwrap_or_default()) - .unwrap_or_default(), + created_index: res.created_index.unwrap_or(0) as u32, + expires_at: res.expires_at as u32, + payment_hash: >::borrow(&res.payment_hash).to_vec(), + payment_secret: res.payment_secret.to_vec(), })); } @@ -554,28 +550,61 @@ impl Node for PluginNodeServer { Ok(Response::new(pb::Empty::default())) } - type StreamIncomingStream = ReceiverStream>; + type StreamNodeEventsStream = ReceiverStream>; - async fn stream_incoming( + async fn stream_node_events( &self, - _req: tonic::Request, - ) -> Result, Status> { - // TODO See if we can just return the broadcast::Receiver - // instead of pulling off broadcast and into an mpsc. + _req: tonic::Request, + ) -> Result, Status> { let (tx, rx) = mpsc::channel(1); let mut bcast = self.events.subscribe(); tokio::spawn(async move { - while let Ok(p) = bcast.recv().await { - match p { + while let Ok(event) = bcast.recv().await { + // Convert Event to NodeEvent protobuf, if applicable + let node_event = match &event { super::Event::IncomingPayment(p) => { - let _ = tx.send(Ok(p)).await; + // Extract the offchain payment details + if let Some(crate::pb::incoming_payment::Details::Offchain(offchain)) = + &p.details + { + Some(pb::NodeEvent { + event: Some(pb::node_event::Event::InvoicePaid(pb::InvoicePaid { + payment_hash: offchain.payment_hash.clone(), + bolt11: offchain.bolt11.clone(), + preimage: offchain.preimage.clone(), + label: offchain.label.clone(), + amount_msat: offchain + .amount + .as_ref() + .and_then(|a| a.unit.as_ref()) + .map(|u| match u { + pb::amount::Unit::Millisatoshi(m) => *m, + pb::amount::Unit::Satoshi(s) => s * 1000, + pb::amount::Unit::Bitcoin(b) => b * 100_000_000_000, + _ => 0, + }) + .unwrap_or(0), + extratlvs: offchain.extratlvs.clone(), + })), + }) + } else { + None + } + } + // Other event types are not exposed to clients + _ => None, + }; + + if let Some(event) = node_event { + if tx.send(Ok(event)).await.is_err() { + // Client disconnected + break; } - _ => {} } } }); - return Ok(Response::new(ReceiverStream::new(rx))); + Ok(Response::new(ReceiverStream::new(rx))) } async fn configure( diff --git a/libs/gl-plugin/src/node/wrapper.rs b/libs/gl-plugin/src/node/wrapper.rs index e13a542a4..a4e125f74 100644 --- a/libs/gl-plugin/src/node/wrapper.rs +++ b/libs/gl-plugin/src/node/wrapper.rs @@ -1191,8 +1191,8 @@ impl WrappedNodeServer { } use crate::pb::{ - node_server::Node as GlNode, Custommsg, Empty, HsmRequest, HsmResponse, IncomingPayment, - LogEntry, LspInvoiceRequest, LspInvoiceResponse, StreamCustommsgRequest, StreamIncomingFilter, + node_server::Node as GlNode, Custommsg, Empty, HsmRequest, HsmResponse, LogEntry, + LspInvoiceRequest, LspInvoiceResponse, NodeEvent, NodeEventsRequest, StreamCustommsgRequest, StreamLogRequest, }; @@ -1201,7 +1201,7 @@ impl GlNode for WrappedNodeServer { type StreamCustommsgStream = ReceiverStream>; type StreamHsmRequestsStream = ReceiverStream>; type StreamLogStream = ReceiverStream>; - type StreamIncomingStream = ReceiverStream>; + type StreamNodeEventsStream = ReceiverStream>; async fn lsp_invoice( &self, @@ -1210,13 +1210,6 @@ impl GlNode for WrappedNodeServer { self.node_server.lsp_invoice(req).await } - async fn stream_incoming( - &self, - req: tonic::Request, - ) -> Result, Status> { - self.node_server.stream_incoming(req).await - } - async fn respond_hsm_request( &self, req: Request, @@ -1266,4 +1259,11 @@ impl GlNode for WrappedNodeServer { ) -> Result, Status> { self.node_server.trampoline_pay(request).await } + + async fn stream_node_events( + &self, + req: tonic::Request, + ) -> Result, Status> { + self.node_server.stream_node_events(req).await + } } diff --git a/libs/gl-sdk/.tasks.yml b/libs/gl-sdk/.tasks.yml index 84880ffa6..b08d1e196 100644 --- a/libs/gl-sdk/.tasks.yml +++ b/libs/gl-sdk/.tasks.yml @@ -43,7 +43,7 @@ tasks: cargo run --bin uniffi-bindgen -- generate \ --library ${CARGO_TARGET_DIR:-target}/{{.PROFILE_DIR}}/libglsdk.{{.LIB_EXT}} \ --language python \ - --out-dir ./libs/gl-sdk/bindings + --out-dir ./libs/gl-sdk/glsdk bindings-kotlin: desc: "Generate Kotlin bindings" diff --git a/libs/gl-sdk/Cargo.toml b/libs/gl-sdk/Cargo.toml index c64a5a37e..7b02e394d 100644 --- a/libs/gl-sdk/Cargo.toml +++ b/libs/gl-sdk/Cargo.toml @@ -13,6 +13,7 @@ gl-client = { version = "0.3.3", path = "../gl-client" } once_cell = "1.21.3" thiserror = "2.0.17" tokio = { version = "1", features = ["sync"] } +tonic.workspace = true tracing = { version = "0.1.43", features = ["async-await", "log"] } uniffi = { version = "0.29.4" } diff --git a/libs/gl-sdk/bindings/glsdk.py b/libs/gl-sdk/bindings/glsdk.py deleted file mode 100644 index 22c6c1b12..000000000 --- a/libs/gl-sdk/bindings/glsdk.py +++ /dev/null @@ -1,2290 +0,0 @@ - - -# This file was autogenerated by some hot garbage in the `uniffi` crate. -# Trust me, you don't want to mess with it! - -# Common helper code. -# -# Ideally this would live in a separate .py file where it can be unittested etc -# in isolation, and perhaps even published as a re-useable package. -# -# However, it's important that the details of how this helper code works (e.g. the -# way that different builtin types are passed across the FFI) exactly match what's -# expected by the rust code on the other side of the interface. In practice right -# now that means coming from the exact some version of `uniffi` that was used to -# compile the rust component. The easiest way to ensure this is to bundle the Python -# helpers directly inline like we're doing here. - -from __future__ import annotations -import os -import sys -import ctypes -import enum -import struct -import contextlib -import datetime -import threading -import itertools -import traceback -import typing -import platform - -# Used for default argument values -_DEFAULT = object() # type: typing.Any - - -class _UniffiRustBuffer(ctypes.Structure): - _fields_ = [ - ("capacity", ctypes.c_uint64), - ("len", ctypes.c_uint64), - ("data", ctypes.POINTER(ctypes.c_char)), - ] - - @staticmethod - def default(): - return _UniffiRustBuffer(0, 0, None) - - @staticmethod - def alloc(size): - return _uniffi_rust_call(_UniffiLib.ffi_glsdk_rustbuffer_alloc, size) - - @staticmethod - def reserve(rbuf, additional): - return _uniffi_rust_call(_UniffiLib.ffi_glsdk_rustbuffer_reserve, rbuf, additional) - - def free(self): - return _uniffi_rust_call(_UniffiLib.ffi_glsdk_rustbuffer_free, self) - - def __str__(self): - return "_UniffiRustBuffer(capacity={}, len={}, data={})".format( - self.capacity, - self.len, - self.data[0:self.len] - ) - - @contextlib.contextmanager - def alloc_with_builder(*args): - """Context-manger to allocate a buffer using a _UniffiRustBufferBuilder. - - The allocated buffer will be automatically freed if an error occurs, ensuring that - we don't accidentally leak it. - """ - builder = _UniffiRustBufferBuilder() - try: - yield builder - except: - builder.discard() - raise - - @contextlib.contextmanager - def consume_with_stream(self): - """Context-manager to consume a buffer using a _UniffiRustBufferStream. - - The _UniffiRustBuffer will be freed once the context-manager exits, ensuring that we don't - leak it even if an error occurs. - """ - try: - s = _UniffiRustBufferStream.from_rust_buffer(self) - yield s - if s.remaining() != 0: - raise RuntimeError("junk data left in buffer at end of consume_with_stream") - finally: - self.free() - - @contextlib.contextmanager - def read_with_stream(self): - """Context-manager to read a buffer using a _UniffiRustBufferStream. - - This is like consume_with_stream, but doesn't free the buffer afterwards. - It should only be used with borrowed `_UniffiRustBuffer` data. - """ - s = _UniffiRustBufferStream.from_rust_buffer(self) - yield s - if s.remaining() != 0: - raise RuntimeError("junk data left in buffer at end of read_with_stream") - -class _UniffiForeignBytes(ctypes.Structure): - _fields_ = [ - ("len", ctypes.c_int32), - ("data", ctypes.POINTER(ctypes.c_char)), - ] - - def __str__(self): - return "_UniffiForeignBytes(len={}, data={})".format(self.len, self.data[0:self.len]) - - -class _UniffiRustBufferStream: - """ - Helper for structured reading of bytes from a _UniffiRustBuffer - """ - - def __init__(self, data, len): - self.data = data - self.len = len - self.offset = 0 - - @classmethod - def from_rust_buffer(cls, buf): - return cls(buf.data, buf.len) - - def remaining(self): - return self.len - self.offset - - def _unpack_from(self, size, format): - if self.offset + size > self.len: - raise InternalError("read past end of rust buffer") - value = struct.unpack(format, self.data[self.offset:self.offset+size])[0] - self.offset += size - return value - - def read(self, size): - if self.offset + size > self.len: - raise InternalError("read past end of rust buffer") - data = self.data[self.offset:self.offset+size] - self.offset += size - return data - - def read_i8(self): - return self._unpack_from(1, ">b") - - def read_u8(self): - return self._unpack_from(1, ">B") - - def read_i16(self): - return self._unpack_from(2, ">h") - - def read_u16(self): - return self._unpack_from(2, ">H") - - def read_i32(self): - return self._unpack_from(4, ">i") - - def read_u32(self): - return self._unpack_from(4, ">I") - - def read_i64(self): - return self._unpack_from(8, ">q") - - def read_u64(self): - return self._unpack_from(8, ">Q") - - def read_float(self): - v = self._unpack_from(4, ">f") - return v - - def read_double(self): - return self._unpack_from(8, ">d") - -class _UniffiRustBufferBuilder: - """ - Helper for structured writing of bytes into a _UniffiRustBuffer. - """ - - def __init__(self): - self.rbuf = _UniffiRustBuffer.alloc(16) - self.rbuf.len = 0 - - def finalize(self): - rbuf = self.rbuf - self.rbuf = None - return rbuf - - def discard(self): - if self.rbuf is not None: - rbuf = self.finalize() - rbuf.free() - - @contextlib.contextmanager - def _reserve(self, num_bytes): - if self.rbuf.len + num_bytes > self.rbuf.capacity: - self.rbuf = _UniffiRustBuffer.reserve(self.rbuf, num_bytes) - yield None - self.rbuf.len += num_bytes - - def _pack_into(self, size, format, value): - with self._reserve(size): - # XXX TODO: I feel like I should be able to use `struct.pack_into` here but can't figure it out. - for i, byte in enumerate(struct.pack(format, value)): - self.rbuf.data[self.rbuf.len + i] = byte - - def write(self, value): - with self._reserve(len(value)): - for i, byte in enumerate(value): - self.rbuf.data[self.rbuf.len + i] = byte - - def write_i8(self, v): - self._pack_into(1, ">b", v) - - def write_u8(self, v): - self._pack_into(1, ">B", v) - - def write_i16(self, v): - self._pack_into(2, ">h", v) - - def write_u16(self, v): - self._pack_into(2, ">H", v) - - def write_i32(self, v): - self._pack_into(4, ">i", v) - - def write_u32(self, v): - self._pack_into(4, ">I", v) - - def write_i64(self, v): - self._pack_into(8, ">q", v) - - def write_u64(self, v): - self._pack_into(8, ">Q", v) - - def write_float(self, v): - self._pack_into(4, ">f", v) - - def write_double(self, v): - self._pack_into(8, ">d", v) - - def write_c_size_t(self, v): - self._pack_into(ctypes.sizeof(ctypes.c_size_t) , "@N", v) -# A handful of classes and functions to support the generated data structures. -# This would be a good candidate for isolating in its own ffi-support lib. - -class InternalError(Exception): - pass - -class _UniffiRustCallStatus(ctypes.Structure): - """ - Error runtime. - """ - _fields_ = [ - ("code", ctypes.c_int8), - ("error_buf", _UniffiRustBuffer), - ] - - # These match the values from the uniffi::rustcalls module - CALL_SUCCESS = 0 - CALL_ERROR = 1 - CALL_UNEXPECTED_ERROR = 2 - - @staticmethod - def default(): - return _UniffiRustCallStatus(code=_UniffiRustCallStatus.CALL_SUCCESS, error_buf=_UniffiRustBuffer.default()) - - def __str__(self): - if self.code == _UniffiRustCallStatus.CALL_SUCCESS: - return "_UniffiRustCallStatus(CALL_SUCCESS)" - elif self.code == _UniffiRustCallStatus.CALL_ERROR: - return "_UniffiRustCallStatus(CALL_ERROR)" - elif self.code == _UniffiRustCallStatus.CALL_UNEXPECTED_ERROR: - return "_UniffiRustCallStatus(CALL_UNEXPECTED_ERROR)" - else: - return "_UniffiRustCallStatus()" - -def _uniffi_rust_call(fn, *args): - # Call a rust function - return _uniffi_rust_call_with_error(None, fn, *args) - -def _uniffi_rust_call_with_error(error_ffi_converter, fn, *args): - # Call a rust function and handle any errors - # - # This function is used for rust calls that return Result<> and therefore can set the CALL_ERROR status code. - # error_ffi_converter must be set to the _UniffiConverter for the error class that corresponds to the result. - call_status = _UniffiRustCallStatus.default() - - args_with_error = args + (ctypes.byref(call_status),) - result = fn(*args_with_error) - _uniffi_check_call_status(error_ffi_converter, call_status) - return result - -def _uniffi_check_call_status(error_ffi_converter, call_status): - if call_status.code == _UniffiRustCallStatus.CALL_SUCCESS: - pass - elif call_status.code == _UniffiRustCallStatus.CALL_ERROR: - if error_ffi_converter is None: - call_status.error_buf.free() - raise InternalError("_uniffi_rust_call_with_error: CALL_ERROR, but error_ffi_converter is None") - else: - raise error_ffi_converter.lift(call_status.error_buf) - elif call_status.code == _UniffiRustCallStatus.CALL_UNEXPECTED_ERROR: - # When the rust code sees a panic, it tries to construct a _UniffiRustBuffer - # with the message. But if that code panics, then it just sends back - # an empty buffer. - if call_status.error_buf.len > 0: - msg = _UniffiConverterString.lift(call_status.error_buf) - else: - msg = "Unknown rust panic" - raise InternalError(msg) - else: - raise InternalError("Invalid _UniffiRustCallStatus code: {}".format( - call_status.code)) - -def _uniffi_trait_interface_call(call_status, make_call, write_return_value): - try: - return write_return_value(make_call()) - except Exception as e: - call_status.code = _UniffiRustCallStatus.CALL_UNEXPECTED_ERROR - call_status.error_buf = _UniffiConverterString.lower(repr(e)) - -def _uniffi_trait_interface_call_with_error(call_status, make_call, write_return_value, error_type, lower_error): - try: - try: - return write_return_value(make_call()) - except error_type as e: - call_status.code = _UniffiRustCallStatus.CALL_ERROR - call_status.error_buf = lower_error(e) - except Exception as e: - call_status.code = _UniffiRustCallStatus.CALL_UNEXPECTED_ERROR - call_status.error_buf = _UniffiConverterString.lower(repr(e)) -class _UniffiHandleMap: - """ - A map where inserting, getting and removing data is synchronized with a lock. - """ - - def __init__(self): - # type Handle = int - self._map = {} # type: Dict[Handle, Any] - self._lock = threading.Lock() - self._counter = itertools.count() - - def insert(self, obj): - with self._lock: - handle = next(self._counter) - self._map[handle] = obj - return handle - - def get(self, handle): - try: - with self._lock: - return self._map[handle] - except KeyError: - raise InternalError("_UniffiHandleMap.get: Invalid handle") - - def remove(self, handle): - try: - with self._lock: - return self._map.pop(handle) - except KeyError: - raise InternalError("_UniffiHandleMap.remove: Invalid handle") - - def __len__(self): - return len(self._map) -# Types conforming to `_UniffiConverterPrimitive` pass themselves directly over the FFI. -class _UniffiConverterPrimitive: - @classmethod - def lift(cls, value): - return value - - @classmethod - def lower(cls, value): - return value - -class _UniffiConverterPrimitiveInt(_UniffiConverterPrimitive): - @classmethod - def check_lower(cls, value): - try: - value = value.__index__() - except Exception: - raise TypeError("'{}' object cannot be interpreted as an integer".format(type(value).__name__)) - if not isinstance(value, int): - raise TypeError("__index__ returned non-int (type {})".format(type(value).__name__)) - if not cls.VALUE_MIN <= value < cls.VALUE_MAX: - raise ValueError("{} requires {} <= value < {}".format(cls.CLASS_NAME, cls.VALUE_MIN, cls.VALUE_MAX)) - -class _UniffiConverterPrimitiveFloat(_UniffiConverterPrimitive): - @classmethod - def check_lower(cls, value): - try: - value = value.__float__() - except Exception: - raise TypeError("must be real number, not {}".format(type(value).__name__)) - if not isinstance(value, float): - raise TypeError("__float__ returned non-float (type {})".format(type(value).__name__)) - -# Helper class for wrapper types that will always go through a _UniffiRustBuffer. -# Classes should inherit from this and implement the `read` and `write` static methods. -class _UniffiConverterRustBuffer: - @classmethod - def lift(cls, rbuf): - with rbuf.consume_with_stream() as stream: - return cls.read(stream) - - @classmethod - def lower(cls, value): - with _UniffiRustBuffer.alloc_with_builder() as builder: - cls.write(value, builder) - return builder.finalize() - -# Contains loading, initialization code, and the FFI Function declarations. -# Define some ctypes FFI types that we use in the library - -""" -Function pointer for a Rust task, which a callback function that takes a opaque pointer -""" -_UNIFFI_RUST_TASK = ctypes.CFUNCTYPE(None, ctypes.c_void_p, ctypes.c_int8) - -def _uniffi_future_callback_t(return_type): - """ - Factory function to create callback function types for async functions - """ - return ctypes.CFUNCTYPE(None, ctypes.c_uint64, return_type, _UniffiRustCallStatus) - -def _uniffi_load_indirect(): - """ - This is how we find and load the dynamic library provided by the component. - For now we just look it up by name. - """ - if sys.platform == "darwin": - libname = "lib{}.dylib" - elif sys.platform.startswith("win"): - # As of python3.8, ctypes does not seem to search $PATH when loading DLLs. - # We could use `os.add_dll_directory` to configure the search path, but - # it doesn't feel right to mess with application-wide settings. Let's - # assume that the `.dll` is next to the `.py` file and load by full path. - libname = os.path.join( - os.path.dirname(__file__), - "{}.dll", - ) - else: - # Anything else must be an ELF platform - Linux, *BSD, Solaris/illumos - libname = "lib{}.so" - - libname = libname.format("glsdk") - path = os.path.join(os.path.dirname(__file__), libname) - lib = ctypes.cdll.LoadLibrary(path) - return lib - -def _uniffi_check_contract_api_version(lib): - # Get the bindings contract version from our ComponentInterface - bindings_contract_version = 29 - # Get the scaffolding contract version by calling the into the dylib - scaffolding_contract_version = lib.ffi_glsdk_uniffi_contract_version() - if bindings_contract_version != scaffolding_contract_version: - raise InternalError("UniFFI contract version mismatch: try cleaning and rebuilding your project") - -def _uniffi_check_api_checksums(lib): - if lib.uniffi_glsdk_checksum_method_credentials_save() != 26677: - raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") - if lib.uniffi_glsdk_checksum_method_handle_stop() != 36432: - raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") - if lib.uniffi_glsdk_checksum_method_node_onchain_receive() != 21676: - raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") - if lib.uniffi_glsdk_checksum_method_node_onchain_send() != 51884: - raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") - if lib.uniffi_glsdk_checksum_method_node_receive() != 24722: - raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") - if lib.uniffi_glsdk_checksum_method_node_send() != 30141: - raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") - if lib.uniffi_glsdk_checksum_method_node_stop() != 20186: - raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") - if lib.uniffi_glsdk_checksum_method_scheduler_recover() != 55514: - raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") - if lib.uniffi_glsdk_checksum_method_scheduler_register() != 20821: - raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") - if lib.uniffi_glsdk_checksum_method_signer_authenticate() != 55935: - raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") - if lib.uniffi_glsdk_checksum_method_signer_node_id() != 43931: - raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") - if lib.uniffi_glsdk_checksum_method_signer_start() != 9404: - raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") - if lib.uniffi_glsdk_checksum_constructor_credentials_load() != 25306: - raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") - if lib.uniffi_glsdk_checksum_constructor_node_new() != 7003: - raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") - if lib.uniffi_glsdk_checksum_constructor_scheduler_new() != 15239: - raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") - if lib.uniffi_glsdk_checksum_constructor_signer_new() != 62159: - raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") - -# A ctypes library to expose the extern-C FFI definitions. -# This is an implementation detail which will be called internally by the public API. - -_UniffiLib = _uniffi_load_indirect() -_UNIFFI_RUST_FUTURE_CONTINUATION_CALLBACK = ctypes.CFUNCTYPE(None,ctypes.c_uint64,ctypes.c_int8, -) -_UNIFFI_FOREIGN_FUTURE_FREE = ctypes.CFUNCTYPE(None,ctypes.c_uint64, -) -_UNIFFI_CALLBACK_INTERFACE_FREE = ctypes.CFUNCTYPE(None,ctypes.c_uint64, -) -class _UniffiForeignFuture(ctypes.Structure): - _fields_ = [ - ("handle", ctypes.c_uint64), - ("free", _UNIFFI_FOREIGN_FUTURE_FREE), - ] -class _UniffiForeignFutureStructU8(ctypes.Structure): - _fields_ = [ - ("return_value", ctypes.c_uint8), - ("call_status", _UniffiRustCallStatus), - ] -_UNIFFI_FOREIGN_FUTURE_COMPLETE_U8 = ctypes.CFUNCTYPE(None,ctypes.c_uint64,_UniffiForeignFutureStructU8, -) -class _UniffiForeignFutureStructI8(ctypes.Structure): - _fields_ = [ - ("return_value", ctypes.c_int8), - ("call_status", _UniffiRustCallStatus), - ] -_UNIFFI_FOREIGN_FUTURE_COMPLETE_I8 = ctypes.CFUNCTYPE(None,ctypes.c_uint64,_UniffiForeignFutureStructI8, -) -class _UniffiForeignFutureStructU16(ctypes.Structure): - _fields_ = [ - ("return_value", ctypes.c_uint16), - ("call_status", _UniffiRustCallStatus), - ] -_UNIFFI_FOREIGN_FUTURE_COMPLETE_U16 = ctypes.CFUNCTYPE(None,ctypes.c_uint64,_UniffiForeignFutureStructU16, -) -class _UniffiForeignFutureStructI16(ctypes.Structure): - _fields_ = [ - ("return_value", ctypes.c_int16), - ("call_status", _UniffiRustCallStatus), - ] -_UNIFFI_FOREIGN_FUTURE_COMPLETE_I16 = ctypes.CFUNCTYPE(None,ctypes.c_uint64,_UniffiForeignFutureStructI16, -) -class _UniffiForeignFutureStructU32(ctypes.Structure): - _fields_ = [ - ("return_value", ctypes.c_uint32), - ("call_status", _UniffiRustCallStatus), - ] -_UNIFFI_FOREIGN_FUTURE_COMPLETE_U32 = ctypes.CFUNCTYPE(None,ctypes.c_uint64,_UniffiForeignFutureStructU32, -) -class _UniffiForeignFutureStructI32(ctypes.Structure): - _fields_ = [ - ("return_value", ctypes.c_int32), - ("call_status", _UniffiRustCallStatus), - ] -_UNIFFI_FOREIGN_FUTURE_COMPLETE_I32 = ctypes.CFUNCTYPE(None,ctypes.c_uint64,_UniffiForeignFutureStructI32, -) -class _UniffiForeignFutureStructU64(ctypes.Structure): - _fields_ = [ - ("return_value", ctypes.c_uint64), - ("call_status", _UniffiRustCallStatus), - ] -_UNIFFI_FOREIGN_FUTURE_COMPLETE_U64 = ctypes.CFUNCTYPE(None,ctypes.c_uint64,_UniffiForeignFutureStructU64, -) -class _UniffiForeignFutureStructI64(ctypes.Structure): - _fields_ = [ - ("return_value", ctypes.c_int64), - ("call_status", _UniffiRustCallStatus), - ] -_UNIFFI_FOREIGN_FUTURE_COMPLETE_I64 = ctypes.CFUNCTYPE(None,ctypes.c_uint64,_UniffiForeignFutureStructI64, -) -class _UniffiForeignFutureStructF32(ctypes.Structure): - _fields_ = [ - ("return_value", ctypes.c_float), - ("call_status", _UniffiRustCallStatus), - ] -_UNIFFI_FOREIGN_FUTURE_COMPLETE_F32 = ctypes.CFUNCTYPE(None,ctypes.c_uint64,_UniffiForeignFutureStructF32, -) -class _UniffiForeignFutureStructF64(ctypes.Structure): - _fields_ = [ - ("return_value", ctypes.c_double), - ("call_status", _UniffiRustCallStatus), - ] -_UNIFFI_FOREIGN_FUTURE_COMPLETE_F64 = ctypes.CFUNCTYPE(None,ctypes.c_uint64,_UniffiForeignFutureStructF64, -) -class _UniffiForeignFutureStructPointer(ctypes.Structure): - _fields_ = [ - ("return_value", ctypes.c_void_p), - ("call_status", _UniffiRustCallStatus), - ] -_UNIFFI_FOREIGN_FUTURE_COMPLETE_POINTER = ctypes.CFUNCTYPE(None,ctypes.c_uint64,_UniffiForeignFutureStructPointer, -) -class _UniffiForeignFutureStructRustBuffer(ctypes.Structure): - _fields_ = [ - ("return_value", _UniffiRustBuffer), - ("call_status", _UniffiRustCallStatus), - ] -_UNIFFI_FOREIGN_FUTURE_COMPLETE_RUST_BUFFER = ctypes.CFUNCTYPE(None,ctypes.c_uint64,_UniffiForeignFutureStructRustBuffer, -) -class _UniffiForeignFutureStructVoid(ctypes.Structure): - _fields_ = [ - ("call_status", _UniffiRustCallStatus), - ] -_UNIFFI_FOREIGN_FUTURE_COMPLETE_VOID = ctypes.CFUNCTYPE(None,ctypes.c_uint64,_UniffiForeignFutureStructVoid, -) -_UniffiLib.uniffi_glsdk_fn_clone_credentials.argtypes = ( - ctypes.c_void_p, - ctypes.POINTER(_UniffiRustCallStatus), -) -_UniffiLib.uniffi_glsdk_fn_clone_credentials.restype = ctypes.c_void_p -_UniffiLib.uniffi_glsdk_fn_free_credentials.argtypes = ( - ctypes.c_void_p, - ctypes.POINTER(_UniffiRustCallStatus), -) -_UniffiLib.uniffi_glsdk_fn_free_credentials.restype = None -_UniffiLib.uniffi_glsdk_fn_constructor_credentials_load.argtypes = ( - _UniffiRustBuffer, - ctypes.POINTER(_UniffiRustCallStatus), -) -_UniffiLib.uniffi_glsdk_fn_constructor_credentials_load.restype = ctypes.c_void_p -_UniffiLib.uniffi_glsdk_fn_method_credentials_save.argtypes = ( - ctypes.c_void_p, - ctypes.POINTER(_UniffiRustCallStatus), -) -_UniffiLib.uniffi_glsdk_fn_method_credentials_save.restype = _UniffiRustBuffer -_UniffiLib.uniffi_glsdk_fn_clone_handle.argtypes = ( - ctypes.c_void_p, - ctypes.POINTER(_UniffiRustCallStatus), -) -_UniffiLib.uniffi_glsdk_fn_clone_handle.restype = ctypes.c_void_p -_UniffiLib.uniffi_glsdk_fn_free_handle.argtypes = ( - ctypes.c_void_p, - ctypes.POINTER(_UniffiRustCallStatus), -) -_UniffiLib.uniffi_glsdk_fn_free_handle.restype = None -_UniffiLib.uniffi_glsdk_fn_method_handle_stop.argtypes = ( - ctypes.c_void_p, - ctypes.POINTER(_UniffiRustCallStatus), -) -_UniffiLib.uniffi_glsdk_fn_method_handle_stop.restype = None -_UniffiLib.uniffi_glsdk_fn_clone_node.argtypes = ( - ctypes.c_void_p, - ctypes.POINTER(_UniffiRustCallStatus), -) -_UniffiLib.uniffi_glsdk_fn_clone_node.restype = ctypes.c_void_p -_UniffiLib.uniffi_glsdk_fn_free_node.argtypes = ( - ctypes.c_void_p, - ctypes.POINTER(_UniffiRustCallStatus), -) -_UniffiLib.uniffi_glsdk_fn_free_node.restype = None -_UniffiLib.uniffi_glsdk_fn_constructor_node_new.argtypes = ( - ctypes.c_void_p, - ctypes.POINTER(_UniffiRustCallStatus), -) -_UniffiLib.uniffi_glsdk_fn_constructor_node_new.restype = ctypes.c_void_p -_UniffiLib.uniffi_glsdk_fn_method_node_onchain_receive.argtypes = ( - ctypes.c_void_p, - ctypes.POINTER(_UniffiRustCallStatus), -) -_UniffiLib.uniffi_glsdk_fn_method_node_onchain_receive.restype = ctypes.c_void_p -_UniffiLib.uniffi_glsdk_fn_method_node_onchain_send.argtypes = ( - ctypes.c_void_p, - _UniffiRustBuffer, - _UniffiRustBuffer, - ctypes.POINTER(_UniffiRustCallStatus), -) -_UniffiLib.uniffi_glsdk_fn_method_node_onchain_send.restype = ctypes.c_void_p -_UniffiLib.uniffi_glsdk_fn_method_node_receive.argtypes = ( - ctypes.c_void_p, - _UniffiRustBuffer, - _UniffiRustBuffer, - _UniffiRustBuffer, - ctypes.POINTER(_UniffiRustCallStatus), -) -_UniffiLib.uniffi_glsdk_fn_method_node_receive.restype = ctypes.c_void_p -_UniffiLib.uniffi_glsdk_fn_method_node_send.argtypes = ( - ctypes.c_void_p, - _UniffiRustBuffer, - _UniffiRustBuffer, - ctypes.POINTER(_UniffiRustCallStatus), -) -_UniffiLib.uniffi_glsdk_fn_method_node_send.restype = ctypes.c_void_p -_UniffiLib.uniffi_glsdk_fn_method_node_stop.argtypes = ( - ctypes.c_void_p, - ctypes.POINTER(_UniffiRustCallStatus), -) -_UniffiLib.uniffi_glsdk_fn_method_node_stop.restype = None -_UniffiLib.uniffi_glsdk_fn_clone_onchainreceiveresponse.argtypes = ( - ctypes.c_void_p, - ctypes.POINTER(_UniffiRustCallStatus), -) -_UniffiLib.uniffi_glsdk_fn_clone_onchainreceiveresponse.restype = ctypes.c_void_p -_UniffiLib.uniffi_glsdk_fn_free_onchainreceiveresponse.argtypes = ( - ctypes.c_void_p, - ctypes.POINTER(_UniffiRustCallStatus), -) -_UniffiLib.uniffi_glsdk_fn_free_onchainreceiveresponse.restype = None -_UniffiLib.uniffi_glsdk_fn_clone_onchainsendresponse.argtypes = ( - ctypes.c_void_p, - ctypes.POINTER(_UniffiRustCallStatus), -) -_UniffiLib.uniffi_glsdk_fn_clone_onchainsendresponse.restype = ctypes.c_void_p -_UniffiLib.uniffi_glsdk_fn_free_onchainsendresponse.argtypes = ( - ctypes.c_void_p, - ctypes.POINTER(_UniffiRustCallStatus), -) -_UniffiLib.uniffi_glsdk_fn_free_onchainsendresponse.restype = None -_UniffiLib.uniffi_glsdk_fn_clone_receiveresponse.argtypes = ( - ctypes.c_void_p, - ctypes.POINTER(_UniffiRustCallStatus), -) -_UniffiLib.uniffi_glsdk_fn_clone_receiveresponse.restype = ctypes.c_void_p -_UniffiLib.uniffi_glsdk_fn_free_receiveresponse.argtypes = ( - ctypes.c_void_p, - ctypes.POINTER(_UniffiRustCallStatus), -) -_UniffiLib.uniffi_glsdk_fn_free_receiveresponse.restype = None -_UniffiLib.uniffi_glsdk_fn_clone_scheduler.argtypes = ( - ctypes.c_void_p, - ctypes.POINTER(_UniffiRustCallStatus), -) -_UniffiLib.uniffi_glsdk_fn_clone_scheduler.restype = ctypes.c_void_p -_UniffiLib.uniffi_glsdk_fn_free_scheduler.argtypes = ( - ctypes.c_void_p, - ctypes.POINTER(_UniffiRustCallStatus), -) -_UniffiLib.uniffi_glsdk_fn_free_scheduler.restype = None -_UniffiLib.uniffi_glsdk_fn_constructor_scheduler_new.argtypes = ( - _UniffiRustBuffer, - ctypes.POINTER(_UniffiRustCallStatus), -) -_UniffiLib.uniffi_glsdk_fn_constructor_scheduler_new.restype = ctypes.c_void_p -_UniffiLib.uniffi_glsdk_fn_method_scheduler_recover.argtypes = ( - ctypes.c_void_p, - ctypes.c_void_p, - ctypes.POINTER(_UniffiRustCallStatus), -) -_UniffiLib.uniffi_glsdk_fn_method_scheduler_recover.restype = ctypes.c_void_p -_UniffiLib.uniffi_glsdk_fn_method_scheduler_register.argtypes = ( - ctypes.c_void_p, - ctypes.c_void_p, - _UniffiRustBuffer, - ctypes.POINTER(_UniffiRustCallStatus), -) -_UniffiLib.uniffi_glsdk_fn_method_scheduler_register.restype = ctypes.c_void_p -_UniffiLib.uniffi_glsdk_fn_clone_sendresponse.argtypes = ( - ctypes.c_void_p, - ctypes.POINTER(_UniffiRustCallStatus), -) -_UniffiLib.uniffi_glsdk_fn_clone_sendresponse.restype = ctypes.c_void_p -_UniffiLib.uniffi_glsdk_fn_free_sendresponse.argtypes = ( - ctypes.c_void_p, - ctypes.POINTER(_UniffiRustCallStatus), -) -_UniffiLib.uniffi_glsdk_fn_free_sendresponse.restype = None -_UniffiLib.uniffi_glsdk_fn_clone_signer.argtypes = ( - ctypes.c_void_p, - ctypes.POINTER(_UniffiRustCallStatus), -) -_UniffiLib.uniffi_glsdk_fn_clone_signer.restype = ctypes.c_void_p -_UniffiLib.uniffi_glsdk_fn_free_signer.argtypes = ( - ctypes.c_void_p, - ctypes.POINTER(_UniffiRustCallStatus), -) -_UniffiLib.uniffi_glsdk_fn_free_signer.restype = None -_UniffiLib.uniffi_glsdk_fn_constructor_signer_new.argtypes = ( - _UniffiRustBuffer, - ctypes.POINTER(_UniffiRustCallStatus), -) -_UniffiLib.uniffi_glsdk_fn_constructor_signer_new.restype = ctypes.c_void_p -_UniffiLib.uniffi_glsdk_fn_method_signer_authenticate.argtypes = ( - ctypes.c_void_p, - ctypes.c_void_p, - ctypes.POINTER(_UniffiRustCallStatus), -) -_UniffiLib.uniffi_glsdk_fn_method_signer_authenticate.restype = ctypes.c_void_p -_UniffiLib.uniffi_glsdk_fn_method_signer_node_id.argtypes = ( - ctypes.c_void_p, - ctypes.POINTER(_UniffiRustCallStatus), -) -_UniffiLib.uniffi_glsdk_fn_method_signer_node_id.restype = _UniffiRustBuffer -_UniffiLib.uniffi_glsdk_fn_method_signer_start.argtypes = ( - ctypes.c_void_p, - ctypes.POINTER(_UniffiRustCallStatus), -) -_UniffiLib.uniffi_glsdk_fn_method_signer_start.restype = ctypes.c_void_p -_UniffiLib.ffi_glsdk_rustbuffer_alloc.argtypes = ( - ctypes.c_uint64, - ctypes.POINTER(_UniffiRustCallStatus), -) -_UniffiLib.ffi_glsdk_rustbuffer_alloc.restype = _UniffiRustBuffer -_UniffiLib.ffi_glsdk_rustbuffer_from_bytes.argtypes = ( - _UniffiForeignBytes, - ctypes.POINTER(_UniffiRustCallStatus), -) -_UniffiLib.ffi_glsdk_rustbuffer_from_bytes.restype = _UniffiRustBuffer -_UniffiLib.ffi_glsdk_rustbuffer_free.argtypes = ( - _UniffiRustBuffer, - ctypes.POINTER(_UniffiRustCallStatus), -) -_UniffiLib.ffi_glsdk_rustbuffer_free.restype = None -_UniffiLib.ffi_glsdk_rustbuffer_reserve.argtypes = ( - _UniffiRustBuffer, - ctypes.c_uint64, - ctypes.POINTER(_UniffiRustCallStatus), -) -_UniffiLib.ffi_glsdk_rustbuffer_reserve.restype = _UniffiRustBuffer -_UniffiLib.ffi_glsdk_rust_future_poll_u8.argtypes = ( - ctypes.c_uint64, - _UNIFFI_RUST_FUTURE_CONTINUATION_CALLBACK, - ctypes.c_uint64, -) -_UniffiLib.ffi_glsdk_rust_future_poll_u8.restype = None -_UniffiLib.ffi_glsdk_rust_future_cancel_u8.argtypes = ( - ctypes.c_uint64, -) -_UniffiLib.ffi_glsdk_rust_future_cancel_u8.restype = None -_UniffiLib.ffi_glsdk_rust_future_free_u8.argtypes = ( - ctypes.c_uint64, -) -_UniffiLib.ffi_glsdk_rust_future_free_u8.restype = None -_UniffiLib.ffi_glsdk_rust_future_complete_u8.argtypes = ( - ctypes.c_uint64, - ctypes.POINTER(_UniffiRustCallStatus), -) -_UniffiLib.ffi_glsdk_rust_future_complete_u8.restype = ctypes.c_uint8 -_UniffiLib.ffi_glsdk_rust_future_poll_i8.argtypes = ( - ctypes.c_uint64, - _UNIFFI_RUST_FUTURE_CONTINUATION_CALLBACK, - ctypes.c_uint64, -) -_UniffiLib.ffi_glsdk_rust_future_poll_i8.restype = None -_UniffiLib.ffi_glsdk_rust_future_cancel_i8.argtypes = ( - ctypes.c_uint64, -) -_UniffiLib.ffi_glsdk_rust_future_cancel_i8.restype = None -_UniffiLib.ffi_glsdk_rust_future_free_i8.argtypes = ( - ctypes.c_uint64, -) -_UniffiLib.ffi_glsdk_rust_future_free_i8.restype = None -_UniffiLib.ffi_glsdk_rust_future_complete_i8.argtypes = ( - ctypes.c_uint64, - ctypes.POINTER(_UniffiRustCallStatus), -) -_UniffiLib.ffi_glsdk_rust_future_complete_i8.restype = ctypes.c_int8 -_UniffiLib.ffi_glsdk_rust_future_poll_u16.argtypes = ( - ctypes.c_uint64, - _UNIFFI_RUST_FUTURE_CONTINUATION_CALLBACK, - ctypes.c_uint64, -) -_UniffiLib.ffi_glsdk_rust_future_poll_u16.restype = None -_UniffiLib.ffi_glsdk_rust_future_cancel_u16.argtypes = ( - ctypes.c_uint64, -) -_UniffiLib.ffi_glsdk_rust_future_cancel_u16.restype = None -_UniffiLib.ffi_glsdk_rust_future_free_u16.argtypes = ( - ctypes.c_uint64, -) -_UniffiLib.ffi_glsdk_rust_future_free_u16.restype = None -_UniffiLib.ffi_glsdk_rust_future_complete_u16.argtypes = ( - ctypes.c_uint64, - ctypes.POINTER(_UniffiRustCallStatus), -) -_UniffiLib.ffi_glsdk_rust_future_complete_u16.restype = ctypes.c_uint16 -_UniffiLib.ffi_glsdk_rust_future_poll_i16.argtypes = ( - ctypes.c_uint64, - _UNIFFI_RUST_FUTURE_CONTINUATION_CALLBACK, - ctypes.c_uint64, -) -_UniffiLib.ffi_glsdk_rust_future_poll_i16.restype = None -_UniffiLib.ffi_glsdk_rust_future_cancel_i16.argtypes = ( - ctypes.c_uint64, -) -_UniffiLib.ffi_glsdk_rust_future_cancel_i16.restype = None -_UniffiLib.ffi_glsdk_rust_future_free_i16.argtypes = ( - ctypes.c_uint64, -) -_UniffiLib.ffi_glsdk_rust_future_free_i16.restype = None -_UniffiLib.ffi_glsdk_rust_future_complete_i16.argtypes = ( - ctypes.c_uint64, - ctypes.POINTER(_UniffiRustCallStatus), -) -_UniffiLib.ffi_glsdk_rust_future_complete_i16.restype = ctypes.c_int16 -_UniffiLib.ffi_glsdk_rust_future_poll_u32.argtypes = ( - ctypes.c_uint64, - _UNIFFI_RUST_FUTURE_CONTINUATION_CALLBACK, - ctypes.c_uint64, -) -_UniffiLib.ffi_glsdk_rust_future_poll_u32.restype = None -_UniffiLib.ffi_glsdk_rust_future_cancel_u32.argtypes = ( - ctypes.c_uint64, -) -_UniffiLib.ffi_glsdk_rust_future_cancel_u32.restype = None -_UniffiLib.ffi_glsdk_rust_future_free_u32.argtypes = ( - ctypes.c_uint64, -) -_UniffiLib.ffi_glsdk_rust_future_free_u32.restype = None -_UniffiLib.ffi_glsdk_rust_future_complete_u32.argtypes = ( - ctypes.c_uint64, - ctypes.POINTER(_UniffiRustCallStatus), -) -_UniffiLib.ffi_glsdk_rust_future_complete_u32.restype = ctypes.c_uint32 -_UniffiLib.ffi_glsdk_rust_future_poll_i32.argtypes = ( - ctypes.c_uint64, - _UNIFFI_RUST_FUTURE_CONTINUATION_CALLBACK, - ctypes.c_uint64, -) -_UniffiLib.ffi_glsdk_rust_future_poll_i32.restype = None -_UniffiLib.ffi_glsdk_rust_future_cancel_i32.argtypes = ( - ctypes.c_uint64, -) -_UniffiLib.ffi_glsdk_rust_future_cancel_i32.restype = None -_UniffiLib.ffi_glsdk_rust_future_free_i32.argtypes = ( - ctypes.c_uint64, -) -_UniffiLib.ffi_glsdk_rust_future_free_i32.restype = None -_UniffiLib.ffi_glsdk_rust_future_complete_i32.argtypes = ( - ctypes.c_uint64, - ctypes.POINTER(_UniffiRustCallStatus), -) -_UniffiLib.ffi_glsdk_rust_future_complete_i32.restype = ctypes.c_int32 -_UniffiLib.ffi_glsdk_rust_future_poll_u64.argtypes = ( - ctypes.c_uint64, - _UNIFFI_RUST_FUTURE_CONTINUATION_CALLBACK, - ctypes.c_uint64, -) -_UniffiLib.ffi_glsdk_rust_future_poll_u64.restype = None -_UniffiLib.ffi_glsdk_rust_future_cancel_u64.argtypes = ( - ctypes.c_uint64, -) -_UniffiLib.ffi_glsdk_rust_future_cancel_u64.restype = None -_UniffiLib.ffi_glsdk_rust_future_free_u64.argtypes = ( - ctypes.c_uint64, -) -_UniffiLib.ffi_glsdk_rust_future_free_u64.restype = None -_UniffiLib.ffi_glsdk_rust_future_complete_u64.argtypes = ( - ctypes.c_uint64, - ctypes.POINTER(_UniffiRustCallStatus), -) -_UniffiLib.ffi_glsdk_rust_future_complete_u64.restype = ctypes.c_uint64 -_UniffiLib.ffi_glsdk_rust_future_poll_i64.argtypes = ( - ctypes.c_uint64, - _UNIFFI_RUST_FUTURE_CONTINUATION_CALLBACK, - ctypes.c_uint64, -) -_UniffiLib.ffi_glsdk_rust_future_poll_i64.restype = None -_UniffiLib.ffi_glsdk_rust_future_cancel_i64.argtypes = ( - ctypes.c_uint64, -) -_UniffiLib.ffi_glsdk_rust_future_cancel_i64.restype = None -_UniffiLib.ffi_glsdk_rust_future_free_i64.argtypes = ( - ctypes.c_uint64, -) -_UniffiLib.ffi_glsdk_rust_future_free_i64.restype = None -_UniffiLib.ffi_glsdk_rust_future_complete_i64.argtypes = ( - ctypes.c_uint64, - ctypes.POINTER(_UniffiRustCallStatus), -) -_UniffiLib.ffi_glsdk_rust_future_complete_i64.restype = ctypes.c_int64 -_UniffiLib.ffi_glsdk_rust_future_poll_f32.argtypes = ( - ctypes.c_uint64, - _UNIFFI_RUST_FUTURE_CONTINUATION_CALLBACK, - ctypes.c_uint64, -) -_UniffiLib.ffi_glsdk_rust_future_poll_f32.restype = None -_UniffiLib.ffi_glsdk_rust_future_cancel_f32.argtypes = ( - ctypes.c_uint64, -) -_UniffiLib.ffi_glsdk_rust_future_cancel_f32.restype = None -_UniffiLib.ffi_glsdk_rust_future_free_f32.argtypes = ( - ctypes.c_uint64, -) -_UniffiLib.ffi_glsdk_rust_future_free_f32.restype = None -_UniffiLib.ffi_glsdk_rust_future_complete_f32.argtypes = ( - ctypes.c_uint64, - ctypes.POINTER(_UniffiRustCallStatus), -) -_UniffiLib.ffi_glsdk_rust_future_complete_f32.restype = ctypes.c_float -_UniffiLib.ffi_glsdk_rust_future_poll_f64.argtypes = ( - ctypes.c_uint64, - _UNIFFI_RUST_FUTURE_CONTINUATION_CALLBACK, - ctypes.c_uint64, -) -_UniffiLib.ffi_glsdk_rust_future_poll_f64.restype = None -_UniffiLib.ffi_glsdk_rust_future_cancel_f64.argtypes = ( - ctypes.c_uint64, -) -_UniffiLib.ffi_glsdk_rust_future_cancel_f64.restype = None -_UniffiLib.ffi_glsdk_rust_future_free_f64.argtypes = ( - ctypes.c_uint64, -) -_UniffiLib.ffi_glsdk_rust_future_free_f64.restype = None -_UniffiLib.ffi_glsdk_rust_future_complete_f64.argtypes = ( - ctypes.c_uint64, - ctypes.POINTER(_UniffiRustCallStatus), -) -_UniffiLib.ffi_glsdk_rust_future_complete_f64.restype = ctypes.c_double -_UniffiLib.ffi_glsdk_rust_future_poll_pointer.argtypes = ( - ctypes.c_uint64, - _UNIFFI_RUST_FUTURE_CONTINUATION_CALLBACK, - ctypes.c_uint64, -) -_UniffiLib.ffi_glsdk_rust_future_poll_pointer.restype = None -_UniffiLib.ffi_glsdk_rust_future_cancel_pointer.argtypes = ( - ctypes.c_uint64, -) -_UniffiLib.ffi_glsdk_rust_future_cancel_pointer.restype = None -_UniffiLib.ffi_glsdk_rust_future_free_pointer.argtypes = ( - ctypes.c_uint64, -) -_UniffiLib.ffi_glsdk_rust_future_free_pointer.restype = None -_UniffiLib.ffi_glsdk_rust_future_complete_pointer.argtypes = ( - ctypes.c_uint64, - ctypes.POINTER(_UniffiRustCallStatus), -) -_UniffiLib.ffi_glsdk_rust_future_complete_pointer.restype = ctypes.c_void_p -_UniffiLib.ffi_glsdk_rust_future_poll_rust_buffer.argtypes = ( - ctypes.c_uint64, - _UNIFFI_RUST_FUTURE_CONTINUATION_CALLBACK, - ctypes.c_uint64, -) -_UniffiLib.ffi_glsdk_rust_future_poll_rust_buffer.restype = None -_UniffiLib.ffi_glsdk_rust_future_cancel_rust_buffer.argtypes = ( - ctypes.c_uint64, -) -_UniffiLib.ffi_glsdk_rust_future_cancel_rust_buffer.restype = None -_UniffiLib.ffi_glsdk_rust_future_free_rust_buffer.argtypes = ( - ctypes.c_uint64, -) -_UniffiLib.ffi_glsdk_rust_future_free_rust_buffer.restype = None -_UniffiLib.ffi_glsdk_rust_future_complete_rust_buffer.argtypes = ( - ctypes.c_uint64, - ctypes.POINTER(_UniffiRustCallStatus), -) -_UniffiLib.ffi_glsdk_rust_future_complete_rust_buffer.restype = _UniffiRustBuffer -_UniffiLib.ffi_glsdk_rust_future_poll_void.argtypes = ( - ctypes.c_uint64, - _UNIFFI_RUST_FUTURE_CONTINUATION_CALLBACK, - ctypes.c_uint64, -) -_UniffiLib.ffi_glsdk_rust_future_poll_void.restype = None -_UniffiLib.ffi_glsdk_rust_future_cancel_void.argtypes = ( - ctypes.c_uint64, -) -_UniffiLib.ffi_glsdk_rust_future_cancel_void.restype = None -_UniffiLib.ffi_glsdk_rust_future_free_void.argtypes = ( - ctypes.c_uint64, -) -_UniffiLib.ffi_glsdk_rust_future_free_void.restype = None -_UniffiLib.ffi_glsdk_rust_future_complete_void.argtypes = ( - ctypes.c_uint64, - ctypes.POINTER(_UniffiRustCallStatus), -) -_UniffiLib.ffi_glsdk_rust_future_complete_void.restype = None -_UniffiLib.uniffi_glsdk_checksum_method_credentials_save.argtypes = ( -) -_UniffiLib.uniffi_glsdk_checksum_method_credentials_save.restype = ctypes.c_uint16 -_UniffiLib.uniffi_glsdk_checksum_method_handle_stop.argtypes = ( -) -_UniffiLib.uniffi_glsdk_checksum_method_handle_stop.restype = ctypes.c_uint16 -_UniffiLib.uniffi_glsdk_checksum_method_node_onchain_receive.argtypes = ( -) -_UniffiLib.uniffi_glsdk_checksum_method_node_onchain_receive.restype = ctypes.c_uint16 -_UniffiLib.uniffi_glsdk_checksum_method_node_onchain_send.argtypes = ( -) -_UniffiLib.uniffi_glsdk_checksum_method_node_onchain_send.restype = ctypes.c_uint16 -_UniffiLib.uniffi_glsdk_checksum_method_node_receive.argtypes = ( -) -_UniffiLib.uniffi_glsdk_checksum_method_node_receive.restype = ctypes.c_uint16 -_UniffiLib.uniffi_glsdk_checksum_method_node_send.argtypes = ( -) -_UniffiLib.uniffi_glsdk_checksum_method_node_send.restype = ctypes.c_uint16 -_UniffiLib.uniffi_glsdk_checksum_method_node_stop.argtypes = ( -) -_UniffiLib.uniffi_glsdk_checksum_method_node_stop.restype = ctypes.c_uint16 -_UniffiLib.uniffi_glsdk_checksum_method_scheduler_recover.argtypes = ( -) -_UniffiLib.uniffi_glsdk_checksum_method_scheduler_recover.restype = ctypes.c_uint16 -_UniffiLib.uniffi_glsdk_checksum_method_scheduler_register.argtypes = ( -) -_UniffiLib.uniffi_glsdk_checksum_method_scheduler_register.restype = ctypes.c_uint16 -_UniffiLib.uniffi_glsdk_checksum_method_signer_authenticate.argtypes = ( -) -_UniffiLib.uniffi_glsdk_checksum_method_signer_authenticate.restype = ctypes.c_uint16 -_UniffiLib.uniffi_glsdk_checksum_method_signer_node_id.argtypes = ( -) -_UniffiLib.uniffi_glsdk_checksum_method_signer_node_id.restype = ctypes.c_uint16 -_UniffiLib.uniffi_glsdk_checksum_method_signer_start.argtypes = ( -) -_UniffiLib.uniffi_glsdk_checksum_method_signer_start.restype = ctypes.c_uint16 -_UniffiLib.uniffi_glsdk_checksum_constructor_credentials_load.argtypes = ( -) -_UniffiLib.uniffi_glsdk_checksum_constructor_credentials_load.restype = ctypes.c_uint16 -_UniffiLib.uniffi_glsdk_checksum_constructor_node_new.argtypes = ( -) -_UniffiLib.uniffi_glsdk_checksum_constructor_node_new.restype = ctypes.c_uint16 -_UniffiLib.uniffi_glsdk_checksum_constructor_scheduler_new.argtypes = ( -) -_UniffiLib.uniffi_glsdk_checksum_constructor_scheduler_new.restype = ctypes.c_uint16 -_UniffiLib.uniffi_glsdk_checksum_constructor_signer_new.argtypes = ( -) -_UniffiLib.uniffi_glsdk_checksum_constructor_signer_new.restype = ctypes.c_uint16 -_UniffiLib.ffi_glsdk_uniffi_contract_version.argtypes = ( -) -_UniffiLib.ffi_glsdk_uniffi_contract_version.restype = ctypes.c_uint32 - -_uniffi_check_contract_api_version(_UniffiLib) -# _uniffi_check_api_checksums(_UniffiLib) - -# Public interface members begin here. - - -class _UniffiConverterUInt64(_UniffiConverterPrimitiveInt): - CLASS_NAME = "u64" - VALUE_MIN = 0 - VALUE_MAX = 2**64 - - @staticmethod - def read(buf): - return buf.read_u64() - - @staticmethod - def write(value, buf): - buf.write_u64(value) - -class _UniffiConverterString: - @staticmethod - def check_lower(value): - if not isinstance(value, str): - raise TypeError("argument must be str, not {}".format(type(value).__name__)) - return value - - @staticmethod - def read(buf): - size = buf.read_i32() - if size < 0: - raise InternalError("Unexpected negative string length") - utf8_bytes = buf.read(size) - return utf8_bytes.decode("utf-8") - - @staticmethod - def write(value, buf): - utf8_bytes = value.encode("utf-8") - buf.write_i32(len(utf8_bytes)) - buf.write(utf8_bytes) - - @staticmethod - def lift(buf): - with buf.consume_with_stream() as stream: - return stream.read(stream.remaining()).decode("utf-8") - - @staticmethod - def lower(value): - with _UniffiRustBuffer.alloc_with_builder() as builder: - builder.write(value.encode("utf-8")) - return builder.finalize() - -class _UniffiConverterBytes(_UniffiConverterRustBuffer): - @staticmethod - def read(buf): - size = buf.read_i32() - if size < 0: - raise InternalError("Unexpected negative byte string length") - return buf.read(size) - - @staticmethod - def check_lower(value): - try: - memoryview(value) - except TypeError: - raise TypeError("a bytes-like object is required, not {!r}".format(type(value).__name__)) - - @staticmethod - def write(value, buf): - buf.write_i32(len(value)) - buf.write(value) - - - - - - - - - - - - - - - - - - - - -# Error -# We want to define each variant as a nested class that's also a subclass, -# which is tricky in Python. To accomplish this we're going to create each -# class separately, then manually add the child classes to the base class's -# __dict__. All of this happens in dummy class to avoid polluting the module -# namespace. -class Error(Exception): - pass - -_UniffiTempError = Error - -class Error: # type: ignore - class DuplicateNode(_UniffiTempError): - def __init__(self, *values): - if len(values) != 1: - raise TypeError(f"Expected 1 arguments, found {len(values)}") - if not isinstance(values[0], str): - raise TypeError(f"unexpected type for tuple element 0 - expected 'str', got '{type(values[0])}'") - super().__init__(", ".join(map(repr, values))) - self._values = values - - def __getitem__(self, index): - return self._values[index] - - def __repr__(self): - return "Error.DuplicateNode({})".format(str(self)) - _UniffiTempError.DuplicateNode = DuplicateNode # type: ignore - class NoSuchNode(_UniffiTempError): - def __init__(self, *values): - if len(values) != 1: - raise TypeError(f"Expected 1 arguments, found {len(values)}") - if not isinstance(values[0], str): - raise TypeError(f"unexpected type for tuple element 0 - expected 'str', got '{type(values[0])}'") - super().__init__(", ".join(map(repr, values))) - self._values = values - - def __getitem__(self, index): - return self._values[index] - - def __repr__(self): - return "Error.NoSuchNode({})".format(str(self)) - _UniffiTempError.NoSuchNode = NoSuchNode # type: ignore - class UnparseableCreds(_UniffiTempError): - def __init__(self): - pass - - def __repr__(self): - return "Error.UnparseableCreds({})".format(str(self)) - _UniffiTempError.UnparseableCreds = UnparseableCreds # type: ignore - class PhraseCorrupted(_UniffiTempError): - def __init__(self): - pass - - def __repr__(self): - return "Error.PhraseCorrupted({})".format(str(self)) - _UniffiTempError.PhraseCorrupted = PhraseCorrupted # type: ignore - class Rpc(_UniffiTempError): - def __init__(self, *values): - if len(values) != 1: - raise TypeError(f"Expected 1 arguments, found {len(values)}") - if not isinstance(values[0], str): - raise TypeError(f"unexpected type for tuple element 0 - expected 'str', got '{type(values[0])}'") - super().__init__(", ".join(map(repr, values))) - self._values = values - - def __getitem__(self, index): - return self._values[index] - - def __repr__(self): - return "Error.Rpc({})".format(str(self)) - _UniffiTempError.Rpc = Rpc # type: ignore - class Argument(_UniffiTempError): - def __init__(self, *values): - if len(values) != 2: - raise TypeError(f"Expected 2 arguments, found {len(values)}") - if not isinstance(values[0], str): - raise TypeError(f"unexpected type for tuple element 0 - expected 'str', got '{type(values[0])}'") - if not isinstance(values[1], str): - raise TypeError(f"unexpected type for tuple element 1 - expected 'str', got '{type(values[1])}'") - super().__init__(", ".join(map(repr, values))) - self._values = values - - def __getitem__(self, index): - return self._values[index] - - def __repr__(self): - return "Error.Argument({})".format(str(self)) - _UniffiTempError.Argument = Argument # type: ignore - class Other(_UniffiTempError): - def __init__(self, *values): - if len(values) != 1: - raise TypeError(f"Expected 1 arguments, found {len(values)}") - if not isinstance(values[0], str): - raise TypeError(f"unexpected type for tuple element 0 - expected 'str', got '{type(values[0])}'") - super().__init__(", ".join(map(repr, values))) - self._values = values - - def __getitem__(self, index): - return self._values[index] - - def __repr__(self): - return "Error.Other({})".format(str(self)) - _UniffiTempError.Other = Other # type: ignore - -Error = _UniffiTempError # type: ignore -del _UniffiTempError - - -class _UniffiConverterTypeError(_UniffiConverterRustBuffer): - @staticmethod - def read(buf): - variant = buf.read_i32() - if variant == 1: - return Error.DuplicateNode( - _UniffiConverterString.read(buf), - ) - if variant == 2: - return Error.NoSuchNode( - _UniffiConverterString.read(buf), - ) - if variant == 3: - return Error.UnparseableCreds( - ) - if variant == 4: - return Error.PhraseCorrupted( - ) - if variant == 5: - return Error.Rpc( - _UniffiConverterString.read(buf), - ) - if variant == 6: - return Error.Argument( - _UniffiConverterString.read(buf), - _UniffiConverterString.read(buf), - ) - if variant == 7: - return Error.Other( - _UniffiConverterString.read(buf), - ) - raise InternalError("Raw enum value doesn't match any cases") - - @staticmethod - def check_lower(value): - if isinstance(value, Error.DuplicateNode): - _UniffiConverterString.check_lower(value._values[0]) - return - if isinstance(value, Error.NoSuchNode): - _UniffiConverterString.check_lower(value._values[0]) - return - if isinstance(value, Error.UnparseableCreds): - return - if isinstance(value, Error.PhraseCorrupted): - return - if isinstance(value, Error.Rpc): - _UniffiConverterString.check_lower(value._values[0]) - return - if isinstance(value, Error.Argument): - _UniffiConverterString.check_lower(value._values[0]) - _UniffiConverterString.check_lower(value._values[1]) - return - if isinstance(value, Error.Other): - _UniffiConverterString.check_lower(value._values[0]) - return - - @staticmethod - def write(value, buf): - if isinstance(value, Error.DuplicateNode): - buf.write_i32(1) - _UniffiConverterString.write(value._values[0], buf) - if isinstance(value, Error.NoSuchNode): - buf.write_i32(2) - _UniffiConverterString.write(value._values[0], buf) - if isinstance(value, Error.UnparseableCreds): - buf.write_i32(3) - if isinstance(value, Error.PhraseCorrupted): - buf.write_i32(4) - if isinstance(value, Error.Rpc): - buf.write_i32(5) - _UniffiConverterString.write(value._values[0], buf) - if isinstance(value, Error.Argument): - buf.write_i32(6) - _UniffiConverterString.write(value._values[0], buf) - _UniffiConverterString.write(value._values[1], buf) - if isinstance(value, Error.Other): - buf.write_i32(7) - _UniffiConverterString.write(value._values[0], buf) - - - - - -class Network(enum.Enum): - BITCOIN = 0 - - REGTEST = 1 - - - -class _UniffiConverterTypeNetwork(_UniffiConverterRustBuffer): - @staticmethod - def read(buf): - variant = buf.read_i32() - if variant == 1: - return Network.BITCOIN - if variant == 2: - return Network.REGTEST - raise InternalError("Raw enum value doesn't match any cases") - - @staticmethod - def check_lower(value): - if value == Network.BITCOIN: - return - if value == Network.REGTEST: - return - raise ValueError(value) - - @staticmethod - def write(value, buf): - if value == Network.BITCOIN: - buf.write_i32(1) - if value == Network.REGTEST: - buf.write_i32(2) - - - - - - - -class PayStatus(enum.Enum): - COMPLETE = 0 - - PENDING = 1 - - FAILED = 2 - - - -class _UniffiConverterTypePayStatus(_UniffiConverterRustBuffer): - @staticmethod - def read(buf): - variant = buf.read_i32() - if variant == 1: - return PayStatus.COMPLETE - if variant == 2: - return PayStatus.PENDING - if variant == 3: - return PayStatus.FAILED - raise InternalError("Raw enum value doesn't match any cases") - - @staticmethod - def check_lower(value): - if value == PayStatus.COMPLETE: - return - if value == PayStatus.PENDING: - return - if value == PayStatus.FAILED: - return - raise ValueError(value) - - @staticmethod - def write(value, buf): - if value == PayStatus.COMPLETE: - buf.write_i32(1) - if value == PayStatus.PENDING: - buf.write_i32(2) - if value == PayStatus.FAILED: - buf.write_i32(3) - - - - - -class _UniffiConverterOptionalUInt64(_UniffiConverterRustBuffer): - @classmethod - def check_lower(cls, value): - if value is not None: - _UniffiConverterUInt64.check_lower(value) - - @classmethod - def write(cls, value, buf): - if value is None: - buf.write_u8(0) - return - - buf.write_u8(1) - _UniffiConverterUInt64.write(value, buf) - - @classmethod - def read(cls, buf): - flag = buf.read_u8() - if flag == 0: - return None - elif flag == 1: - return _UniffiConverterUInt64.read(buf) - else: - raise InternalError("Unexpected flag byte for optional type") - - - -class _UniffiConverterOptionalString(_UniffiConverterRustBuffer): - @classmethod - def check_lower(cls, value): - if value is not None: - _UniffiConverterString.check_lower(value) - - @classmethod - def write(cls, value, buf): - if value is None: - buf.write_u8(0) - return - - buf.write_u8(1) - _UniffiConverterString.write(value, buf) - - @classmethod - def read(cls, buf): - flag = buf.read_u8() - if flag == 0: - return None - elif flag == 1: - return _UniffiConverterString.read(buf) - else: - raise InternalError("Unexpected flag byte for optional type") - -# objects. -class CredentialsProtocol(typing.Protocol): - """ - `Credentials` is a container for `node_id`, the mTLS client - certificate used to authenticate a client against a node, as well - as the seed secret if present. If no seed is present in the - credentials, then the `Client` will not start a signer in the - background. - """ - - def save(self, ): - raise NotImplementedError -# Credentials is a Rust-only trait - it's a wrapper around a Rust implementation. -class Credentials(): - """ - `Credentials` is a container for `node_id`, the mTLS client - certificate used to authenticate a client against a node, as well - as the seed secret if present. If no seed is present in the - credentials, then the `Client` will not start a signer in the - background. - """ - - _pointer: ctypes.c_void_p - - def __init__(self, *args, **kwargs): - raise ValueError("This class has no default constructor") - - def __del__(self): - # In case of partial initialization of instances. - pointer = getattr(self, "_pointer", None) - if pointer is not None: - _uniffi_rust_call(_UniffiLib.uniffi_glsdk_fn_free_credentials, pointer) - - def _uniffi_clone_pointer(self): - return _uniffi_rust_call(_UniffiLib.uniffi_glsdk_fn_clone_credentials, self._pointer) - - # Used by alternative constructors or any methods which return this type. - @classmethod - def _make_instance_(cls, pointer): - # Lightly yucky way to bypass the usual __init__ logic - # and just create a new instance with the required pointer. - inst = cls.__new__(cls) - inst._pointer = pointer - return inst - @classmethod - def load(cls, raw: "bytes"): - _UniffiConverterBytes.check_lower(raw) - - # Call the (fallible) function before creating any half-baked object instances. - pointer = _uniffi_rust_call_with_error(_UniffiConverterTypeError,_UniffiLib.uniffi_glsdk_fn_constructor_credentials_load, - _UniffiConverterBytes.lower(raw)) - return cls._make_instance_(pointer) - - - - def save(self, ) -> "bytes": - return _UniffiConverterBytes.lift( - _uniffi_rust_call_with_error(_UniffiConverterTypeError,_UniffiLib.uniffi_glsdk_fn_method_credentials_save,self._uniffi_clone_pointer(),) - ) - - - - - - -class _UniffiConverterTypeCredentials: - - @staticmethod - def lift(value: int): - return Credentials._make_instance_(value) - - @staticmethod - def check_lower(value: Credentials): - if not isinstance(value, Credentials): - raise TypeError("Expected Credentials instance, {} found".format(type(value).__name__)) - - @staticmethod - def lower(value: CredentialsProtocol): - if not isinstance(value, Credentials): - raise TypeError("Expected Credentials instance, {} found".format(type(value).__name__)) - return value._uniffi_clone_pointer() - - @classmethod - def read(cls, buf: _UniffiRustBuffer): - ptr = buf.read_u64() - if ptr == 0: - raise InternalError("Raw pointer value was null") - return cls.lift(ptr) - - @classmethod - def write(cls, value: CredentialsProtocol, buf: _UniffiRustBuffer): - buf.write_u64(cls.lower(value)) -class HandleProtocol(typing.Protocol): - """ - A handle to interact with a signer loop running and processing - requests in the background. Used primarily to stop the loop and - exiting the signer. - """ - - def stop(self, ): - raise NotImplementedError -# Handle is a Rust-only trait - it's a wrapper around a Rust implementation. -class Handle(): - """ - A handle to interact with a signer loop running and processing - requests in the background. Used primarily to stop the loop and - exiting the signer. - """ - - _pointer: ctypes.c_void_p - - def __init__(self, *args, **kwargs): - raise ValueError("This class has no default constructor") - - def __del__(self): - # In case of partial initialization of instances. - pointer = getattr(self, "_pointer", None) - if pointer is not None: - _uniffi_rust_call(_UniffiLib.uniffi_glsdk_fn_free_handle, pointer) - - def _uniffi_clone_pointer(self): - return _uniffi_rust_call(_UniffiLib.uniffi_glsdk_fn_clone_handle, self._pointer) - - # Used by alternative constructors or any methods which return this type. - @classmethod - def _make_instance_(cls, pointer): - # Lightly yucky way to bypass the usual __init__ logic - # and just create a new instance with the required pointer. - inst = cls.__new__(cls) - inst._pointer = pointer - return inst - - - def stop(self, ) -> None: - _uniffi_rust_call(_UniffiLib.uniffi_glsdk_fn_method_handle_stop,self._uniffi_clone_pointer(),) - - - - - - - -class _UniffiConverterTypeHandle: - - @staticmethod - def lift(value: int): - return Handle._make_instance_(value) - - @staticmethod - def check_lower(value: Handle): - if not isinstance(value, Handle): - raise TypeError("Expected Handle instance, {} found".format(type(value).__name__)) - - @staticmethod - def lower(value: HandleProtocol): - if not isinstance(value, Handle): - raise TypeError("Expected Handle instance, {} found".format(type(value).__name__)) - return value._uniffi_clone_pointer() - - @classmethod - def read(cls, buf: _UniffiRustBuffer): - ptr = buf.read_u64() - if ptr == 0: - raise InternalError("Raw pointer value was null") - return cls.lift(ptr) - - @classmethod - def write(cls, value: HandleProtocol, buf: _UniffiRustBuffer): - buf.write_u64(cls.lower(value)) -class NodeProtocol(typing.Protocol): - """ - The `Node` is an RPC stub representing the node running in the - cloud. It is the main entrypoint to interact with the node. - """ - - def onchain_receive(self, ): - raise NotImplementedError - def onchain_send(self, destination: "str",amount_or_all: "str"): - raise NotImplementedError - def receive(self, label: "str",description: "str",amount_msat: "typing.Optional[int]"): - """ - Receive an off-chain payment. - - This method generates a request for a payment, also called an - invoice, that encodes all the information, including amount - and destination, for a prospective sender to send a lightning - payment. The invoice includes negotiation of an LSPS2 / JIT - channel, meaning that if there is no channel sufficient to - receive the requested funds, the node will negotiate an - opening, and when/if executed the payment will cause a channel - to be created, and the incoming payment to be forwarded. - """ - - raise NotImplementedError - def send(self, invoice: "str",amount_msat: "typing.Optional[int]"): - raise NotImplementedError - def stop(self, ): - """ - Stop the node if it is currently running. - """ - - raise NotImplementedError -# Node is a Rust-only trait - it's a wrapper around a Rust implementation. -class Node(): - """ - The `Node` is an RPC stub representing the node running in the - cloud. It is the main entrypoint to interact with the node. - """ - - _pointer: ctypes.c_void_p - def __init__(self, credentials: "Credentials"): - _UniffiConverterTypeCredentials.check_lower(credentials) - - self._pointer = _uniffi_rust_call_with_error(_UniffiConverterTypeError,_UniffiLib.uniffi_glsdk_fn_constructor_node_new, - _UniffiConverterTypeCredentials.lower(credentials)) - - def __del__(self): - # In case of partial initialization of instances. - pointer = getattr(self, "_pointer", None) - if pointer is not None: - _uniffi_rust_call(_UniffiLib.uniffi_glsdk_fn_free_node, pointer) - - def _uniffi_clone_pointer(self): - return _uniffi_rust_call(_UniffiLib.uniffi_glsdk_fn_clone_node, self._pointer) - - # Used by alternative constructors or any methods which return this type. - @classmethod - def _make_instance_(cls, pointer): - # Lightly yucky way to bypass the usual __init__ logic - # and just create a new instance with the required pointer. - inst = cls.__new__(cls) - inst._pointer = pointer - return inst - - - def onchain_receive(self, ) -> "OnchainReceiveResponse": - return _UniffiConverterTypeOnchainReceiveResponse.lift( - _uniffi_rust_call_with_error(_UniffiConverterTypeError,_UniffiLib.uniffi_glsdk_fn_method_node_onchain_receive,self._uniffi_clone_pointer(),) - ) - - - - - - def onchain_send(self, destination: "str",amount_or_all: "str") -> "OnchainSendResponse": - _UniffiConverterString.check_lower(destination) - - _UniffiConverterString.check_lower(amount_or_all) - - return _UniffiConverterTypeOnchainSendResponse.lift( - _uniffi_rust_call_with_error(_UniffiConverterTypeError,_UniffiLib.uniffi_glsdk_fn_method_node_onchain_send,self._uniffi_clone_pointer(), - _UniffiConverterString.lower(destination), - _UniffiConverterString.lower(amount_or_all)) - ) - - - - - - def receive(self, label: "str",description: "str",amount_msat: "typing.Optional[int]") -> "ReceiveResponse": - """ - Receive an off-chain payment. - - This method generates a request for a payment, also called an - invoice, that encodes all the information, including amount - and destination, for a prospective sender to send a lightning - payment. The invoice includes negotiation of an LSPS2 / JIT - channel, meaning that if there is no channel sufficient to - receive the requested funds, the node will negotiate an - opening, and when/if executed the payment will cause a channel - to be created, and the incoming payment to be forwarded. - """ - - _UniffiConverterString.check_lower(label) - - _UniffiConverterString.check_lower(description) - - _UniffiConverterOptionalUInt64.check_lower(amount_msat) - - return _UniffiConverterTypeReceiveResponse.lift( - _uniffi_rust_call_with_error(_UniffiConverterTypeError,_UniffiLib.uniffi_glsdk_fn_method_node_receive,self._uniffi_clone_pointer(), - _UniffiConverterString.lower(label), - _UniffiConverterString.lower(description), - _UniffiConverterOptionalUInt64.lower(amount_msat)) - ) - - - - - - def send(self, invoice: "str",amount_msat: "typing.Optional[int]") -> "SendResponse": - _UniffiConverterString.check_lower(invoice) - - _UniffiConverterOptionalUInt64.check_lower(amount_msat) - - return _UniffiConverterTypeSendResponse.lift( - _uniffi_rust_call_with_error(_UniffiConverterTypeError,_UniffiLib.uniffi_glsdk_fn_method_node_send,self._uniffi_clone_pointer(), - _UniffiConverterString.lower(invoice), - _UniffiConverterOptionalUInt64.lower(amount_msat)) - ) - - - - - - def stop(self, ) -> None: - """ - Stop the node if it is currently running. - """ - - _uniffi_rust_call_with_error(_UniffiConverterTypeError,_UniffiLib.uniffi_glsdk_fn_method_node_stop,self._uniffi_clone_pointer(),) - - - - - - - -class _UniffiConverterTypeNode: - - @staticmethod - def lift(value: int): - return Node._make_instance_(value) - - @staticmethod - def check_lower(value: Node): - if not isinstance(value, Node): - raise TypeError("Expected Node instance, {} found".format(type(value).__name__)) - - @staticmethod - def lower(value: NodeProtocol): - if not isinstance(value, Node): - raise TypeError("Expected Node instance, {} found".format(type(value).__name__)) - return value._uniffi_clone_pointer() - - @classmethod - def read(cls, buf: _UniffiRustBuffer): - ptr = buf.read_u64() - if ptr == 0: - raise InternalError("Raw pointer value was null") - return cls.lift(ptr) - - @classmethod - def write(cls, value: NodeProtocol, buf: _UniffiRustBuffer): - buf.write_u64(cls.lower(value)) -class OnchainReceiveResponseProtocol(typing.Protocol): - pass -# OnchainReceiveResponse is a Rust-only trait - it's a wrapper around a Rust implementation. -class OnchainReceiveResponse(): - _pointer: ctypes.c_void_p - - def __init__(self, *args, **kwargs): - raise ValueError("This class has no default constructor") - - def __del__(self): - # In case of partial initialization of instances. - pointer = getattr(self, "_pointer", None) - if pointer is not None: - _uniffi_rust_call(_UniffiLib.uniffi_glsdk_fn_free_onchainreceiveresponse, pointer) - - def _uniffi_clone_pointer(self): - return _uniffi_rust_call(_UniffiLib.uniffi_glsdk_fn_clone_onchainreceiveresponse, self._pointer) - - # Used by alternative constructors or any methods which return this type. - @classmethod - def _make_instance_(cls, pointer): - # Lightly yucky way to bypass the usual __init__ logic - # and just create a new instance with the required pointer. - inst = cls.__new__(cls) - inst._pointer = pointer - return inst - - - -class _UniffiConverterTypeOnchainReceiveResponse: - - @staticmethod - def lift(value: int): - return OnchainReceiveResponse._make_instance_(value) - - @staticmethod - def check_lower(value: OnchainReceiveResponse): - if not isinstance(value, OnchainReceiveResponse): - raise TypeError("Expected OnchainReceiveResponse instance, {} found".format(type(value).__name__)) - - @staticmethod - def lower(value: OnchainReceiveResponseProtocol): - if not isinstance(value, OnchainReceiveResponse): - raise TypeError("Expected OnchainReceiveResponse instance, {} found".format(type(value).__name__)) - return value._uniffi_clone_pointer() - - @classmethod - def read(cls, buf: _UniffiRustBuffer): - ptr = buf.read_u64() - if ptr == 0: - raise InternalError("Raw pointer value was null") - return cls.lift(ptr) - - @classmethod - def write(cls, value: OnchainReceiveResponseProtocol, buf: _UniffiRustBuffer): - buf.write_u64(cls.lower(value)) -class OnchainSendResponseProtocol(typing.Protocol): - pass -# OnchainSendResponse is a Rust-only trait - it's a wrapper around a Rust implementation. -class OnchainSendResponse(): - _pointer: ctypes.c_void_p - - def __init__(self, *args, **kwargs): - raise ValueError("This class has no default constructor") - - def __del__(self): - # In case of partial initialization of instances. - pointer = getattr(self, "_pointer", None) - if pointer is not None: - _uniffi_rust_call(_UniffiLib.uniffi_glsdk_fn_free_onchainsendresponse, pointer) - - def _uniffi_clone_pointer(self): - return _uniffi_rust_call(_UniffiLib.uniffi_glsdk_fn_clone_onchainsendresponse, self._pointer) - - # Used by alternative constructors or any methods which return this type. - @classmethod - def _make_instance_(cls, pointer): - # Lightly yucky way to bypass the usual __init__ logic - # and just create a new instance with the required pointer. - inst = cls.__new__(cls) - inst._pointer = pointer - return inst - - - -class _UniffiConverterTypeOnchainSendResponse: - - @staticmethod - def lift(value: int): - return OnchainSendResponse._make_instance_(value) - - @staticmethod - def check_lower(value: OnchainSendResponse): - if not isinstance(value, OnchainSendResponse): - raise TypeError("Expected OnchainSendResponse instance, {} found".format(type(value).__name__)) - - @staticmethod - def lower(value: OnchainSendResponseProtocol): - if not isinstance(value, OnchainSendResponse): - raise TypeError("Expected OnchainSendResponse instance, {} found".format(type(value).__name__)) - return value._uniffi_clone_pointer() - - @classmethod - def read(cls, buf: _UniffiRustBuffer): - ptr = buf.read_u64() - if ptr == 0: - raise InternalError("Raw pointer value was null") - return cls.lift(ptr) - - @classmethod - def write(cls, value: OnchainSendResponseProtocol, buf: _UniffiRustBuffer): - buf.write_u64(cls.lower(value)) -class ReceiveResponseProtocol(typing.Protocol): - pass -# ReceiveResponse is a Rust-only trait - it's a wrapper around a Rust implementation. -class ReceiveResponse(): - _pointer: ctypes.c_void_p - - def __init__(self, *args, **kwargs): - raise ValueError("This class has no default constructor") - - def __del__(self): - # In case of partial initialization of instances. - pointer = getattr(self, "_pointer", None) - if pointer is not None: - _uniffi_rust_call(_UniffiLib.uniffi_glsdk_fn_free_receiveresponse, pointer) - - def _uniffi_clone_pointer(self): - return _uniffi_rust_call(_UniffiLib.uniffi_glsdk_fn_clone_receiveresponse, self._pointer) - - # Used by alternative constructors or any methods which return this type. - @classmethod - def _make_instance_(cls, pointer): - # Lightly yucky way to bypass the usual __init__ logic - # and just create a new instance with the required pointer. - inst = cls.__new__(cls) - inst._pointer = pointer - return inst - - - -class _UniffiConverterTypeReceiveResponse: - - @staticmethod - def lift(value: int): - return ReceiveResponse._make_instance_(value) - - @staticmethod - def check_lower(value: ReceiveResponse): - if not isinstance(value, ReceiveResponse): - raise TypeError("Expected ReceiveResponse instance, {} found".format(type(value).__name__)) - - @staticmethod - def lower(value: ReceiveResponseProtocol): - if not isinstance(value, ReceiveResponse): - raise TypeError("Expected ReceiveResponse instance, {} found".format(type(value).__name__)) - return value._uniffi_clone_pointer() - - @classmethod - def read(cls, buf: _UniffiRustBuffer): - ptr = buf.read_u64() - if ptr == 0: - raise InternalError("Raw pointer value was null") - return cls.lift(ptr) - - @classmethod - def write(cls, value: ReceiveResponseProtocol, buf: _UniffiRustBuffer): - buf.write_u64(cls.lower(value)) -class SchedulerProtocol(typing.Protocol): - def recover(self, signer: "Signer"): - raise NotImplementedError - def register(self, signer: "Signer",code: "typing.Optional[str]"): - raise NotImplementedError -# Scheduler is a Rust-only trait - it's a wrapper around a Rust implementation. -class Scheduler(): - _pointer: ctypes.c_void_p - def __init__(self, network: "Network"): - """ - Create a `Scheduler` instance configured with the Greenlight - production service pre-configured. - """ - - _UniffiConverterTypeNetwork.check_lower(network) - - self._pointer = _uniffi_rust_call_with_error(_UniffiConverterTypeError,_UniffiLib.uniffi_glsdk_fn_constructor_scheduler_new, - _UniffiConverterTypeNetwork.lower(network)) - - def __del__(self): - # In case of partial initialization of instances. - pointer = getattr(self, "_pointer", None) - if pointer is not None: - _uniffi_rust_call(_UniffiLib.uniffi_glsdk_fn_free_scheduler, pointer) - - def _uniffi_clone_pointer(self): - return _uniffi_rust_call(_UniffiLib.uniffi_glsdk_fn_clone_scheduler, self._pointer) - - # Used by alternative constructors or any methods which return this type. - @classmethod - def _make_instance_(cls, pointer): - # Lightly yucky way to bypass the usual __init__ logic - # and just create a new instance with the required pointer. - inst = cls.__new__(cls) - inst._pointer = pointer - return inst - - - def recover(self, signer: "Signer") -> "Credentials": - _UniffiConverterTypeSigner.check_lower(signer) - - return _UniffiConverterTypeCredentials.lift( - _uniffi_rust_call_with_error(_UniffiConverterTypeError,_UniffiLib.uniffi_glsdk_fn_method_scheduler_recover,self._uniffi_clone_pointer(), - _UniffiConverterTypeSigner.lower(signer)) - ) - - - - - - def register(self, signer: "Signer",code: "typing.Optional[str]") -> "Credentials": - _UniffiConverterTypeSigner.check_lower(signer) - - _UniffiConverterOptionalString.check_lower(code) - - return _UniffiConverterTypeCredentials.lift( - _uniffi_rust_call_with_error(_UniffiConverterTypeError,_UniffiLib.uniffi_glsdk_fn_method_scheduler_register,self._uniffi_clone_pointer(), - _UniffiConverterTypeSigner.lower(signer), - _UniffiConverterOptionalString.lower(code)) - ) - - - - - - -class _UniffiConverterTypeScheduler: - - @staticmethod - def lift(value: int): - return Scheduler._make_instance_(value) - - @staticmethod - def check_lower(value: Scheduler): - if not isinstance(value, Scheduler): - raise TypeError("Expected Scheduler instance, {} found".format(type(value).__name__)) - - @staticmethod - def lower(value: SchedulerProtocol): - if not isinstance(value, Scheduler): - raise TypeError("Expected Scheduler instance, {} found".format(type(value).__name__)) - return value._uniffi_clone_pointer() - - @classmethod - def read(cls, buf: _UniffiRustBuffer): - ptr = buf.read_u64() - if ptr == 0: - raise InternalError("Raw pointer value was null") - return cls.lift(ptr) - - @classmethod - def write(cls, value: SchedulerProtocol, buf: _UniffiRustBuffer): - buf.write_u64(cls.lower(value)) -class SendResponseProtocol(typing.Protocol): - pass -# SendResponse is a Rust-only trait - it's a wrapper around a Rust implementation. -class SendResponse(): - _pointer: ctypes.c_void_p - - def __init__(self, *args, **kwargs): - raise ValueError("This class has no default constructor") - - def __del__(self): - # In case of partial initialization of instances. - pointer = getattr(self, "_pointer", None) - if pointer is not None: - _uniffi_rust_call(_UniffiLib.uniffi_glsdk_fn_free_sendresponse, pointer) - - def _uniffi_clone_pointer(self): - return _uniffi_rust_call(_UniffiLib.uniffi_glsdk_fn_clone_sendresponse, self._pointer) - - # Used by alternative constructors or any methods which return this type. - @classmethod - def _make_instance_(cls, pointer): - # Lightly yucky way to bypass the usual __init__ logic - # and just create a new instance with the required pointer. - inst = cls.__new__(cls) - inst._pointer = pointer - return inst - - - -class _UniffiConverterTypeSendResponse: - - @staticmethod - def lift(value: int): - return SendResponse._make_instance_(value) - - @staticmethod - def check_lower(value: SendResponse): - if not isinstance(value, SendResponse): - raise TypeError("Expected SendResponse instance, {} found".format(type(value).__name__)) - - @staticmethod - def lower(value: SendResponseProtocol): - if not isinstance(value, SendResponse): - raise TypeError("Expected SendResponse instance, {} found".format(type(value).__name__)) - return value._uniffi_clone_pointer() - - @classmethod - def read(cls, buf: _UniffiRustBuffer): - ptr = buf.read_u64() - if ptr == 0: - raise InternalError("Raw pointer value was null") - return cls.lift(ptr) - - @classmethod - def write(cls, value: SendResponseProtocol, buf: _UniffiRustBuffer): - buf.write_u64(cls.lower(value)) -class SignerProtocol(typing.Protocol): - def authenticate(self, creds: "Credentials"): - raise NotImplementedError - def node_id(self, ): - raise NotImplementedError - def start(self, ): - raise NotImplementedError -# Signer is a Rust-only trait - it's a wrapper around a Rust implementation. -class Signer(): - _pointer: ctypes.c_void_p - def __init__(self, phrase: "str"): - _UniffiConverterString.check_lower(phrase) - - self._pointer = _uniffi_rust_call_with_error(_UniffiConverterTypeError,_UniffiLib.uniffi_glsdk_fn_constructor_signer_new, - _UniffiConverterString.lower(phrase)) - - def __del__(self): - # In case of partial initialization of instances. - pointer = getattr(self, "_pointer", None) - if pointer is not None: - _uniffi_rust_call(_UniffiLib.uniffi_glsdk_fn_free_signer, pointer) - - def _uniffi_clone_pointer(self): - return _uniffi_rust_call(_UniffiLib.uniffi_glsdk_fn_clone_signer, self._pointer) - - # Used by alternative constructors or any methods which return this type. - @classmethod - def _make_instance_(cls, pointer): - # Lightly yucky way to bypass the usual __init__ logic - # and just create a new instance with the required pointer. - inst = cls.__new__(cls) - inst._pointer = pointer - return inst - - - def authenticate(self, creds: "Credentials") -> "Signer": - _UniffiConverterTypeCredentials.check_lower(creds) - - return _UniffiConverterTypeSigner.lift( - _uniffi_rust_call_with_error(_UniffiConverterTypeError,_UniffiLib.uniffi_glsdk_fn_method_signer_authenticate,self._uniffi_clone_pointer(), - _UniffiConverterTypeCredentials.lower(creds)) - ) - - - - - - def node_id(self, ) -> "bytes": - return _UniffiConverterBytes.lift( - _uniffi_rust_call(_UniffiLib.uniffi_glsdk_fn_method_signer_node_id,self._uniffi_clone_pointer(),) - ) - - - - - - def start(self, ) -> "Handle": - return _UniffiConverterTypeHandle.lift( - _uniffi_rust_call_with_error(_UniffiConverterTypeError,_UniffiLib.uniffi_glsdk_fn_method_signer_start,self._uniffi_clone_pointer(),) - ) - - - - - - -class _UniffiConverterTypeSigner: - - @staticmethod - def lift(value: int): - return Signer._make_instance_(value) - - @staticmethod - def check_lower(value: Signer): - if not isinstance(value, Signer): - raise TypeError("Expected Signer instance, {} found".format(type(value).__name__)) - - @staticmethod - def lower(value: SignerProtocol): - if not isinstance(value, Signer): - raise TypeError("Expected Signer instance, {} found".format(type(value).__name__)) - return value._uniffi_clone_pointer() - - @classmethod - def read(cls, buf: _UniffiRustBuffer): - ptr = buf.read_u64() - if ptr == 0: - raise InternalError("Raw pointer value was null") - return cls.lift(ptr) - - @classmethod - def write(cls, value: SignerProtocol, buf: _UniffiRustBuffer): - buf.write_u64(cls.lower(value)) - -# Async support - -__all__ = [ - "InternalError", - "Error", - "Network", - "PayStatus", - "Credentials", - "Handle", - "Node", - "OnchainReceiveResponse", - "OnchainSendResponse", - "ReceiveResponse", - "Scheduler", - "SendResponse", - "Signer", -] - diff --git a/libs/gl-sdk/glsdk/glsdk.py b/libs/gl-sdk/glsdk/glsdk.py index 78a9bef28..340fbee8b 100644 --- a/libs/gl-sdk/glsdk/glsdk.py +++ b/libs/gl-sdk/glsdk/glsdk.py @@ -460,8 +460,32 @@ def _uniffi_check_contract_api_version(lib): raise InternalError("UniFFI contract version mismatch: try cleaning and rebuilding your project") def _uniffi_check_api_checksums(lib): + if lib.uniffi_glsdk_checksum_method_credentials_save() != 26677: + raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") if lib.uniffi_glsdk_checksum_method_handle_stop() != 36432: raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + if lib.uniffi_glsdk_checksum_method_node_get_info() != 39460: + raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + if lib.uniffi_glsdk_checksum_method_node_list_funds() != 21692: + raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + if lib.uniffi_glsdk_checksum_method_node_list_peer_channels() != 35210: + raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + if lib.uniffi_glsdk_checksum_method_node_list_peers() != 29567: + raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + if lib.uniffi_glsdk_checksum_method_node_onchain_receive() != 57530: + raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + if lib.uniffi_glsdk_checksum_method_node_onchain_send() != 44346: + raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + if lib.uniffi_glsdk_checksum_method_node_receive() != 39761: + raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + if lib.uniffi_glsdk_checksum_method_node_send() != 4348: + raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + if lib.uniffi_glsdk_checksum_method_node_stop() != 20186: + raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + if lib.uniffi_glsdk_checksum_method_node_stream_node_events() != 5933: + raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + if lib.uniffi_glsdk_checksum_method_nodeeventstream_next() != 12635: + raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") if lib.uniffi_glsdk_checksum_method_scheduler_recover() != 55514: raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") if lib.uniffi_glsdk_checksum_method_scheduler_register() != 20821: @@ -601,6 +625,11 @@ class _UniffiForeignFutureStructVoid(ctypes.Structure): ctypes.POINTER(_UniffiRustCallStatus), ) _UniffiLib.uniffi_glsdk_fn_constructor_credentials_load.restype = ctypes.c_void_p +_UniffiLib.uniffi_glsdk_fn_method_credentials_save.argtypes = ( + ctypes.c_void_p, + ctypes.POINTER(_UniffiRustCallStatus), +) +_UniffiLib.uniffi_glsdk_fn_method_credentials_save.restype = _UniffiRustBuffer _UniffiLib.uniffi_glsdk_fn_clone_handle.argtypes = ( ctypes.c_void_p, ctypes.POINTER(_UniffiRustCallStatus), @@ -631,6 +660,78 @@ class _UniffiForeignFutureStructVoid(ctypes.Structure): ctypes.POINTER(_UniffiRustCallStatus), ) _UniffiLib.uniffi_glsdk_fn_constructor_node_new.restype = ctypes.c_void_p +_UniffiLib.uniffi_glsdk_fn_method_node_get_info.argtypes = ( + ctypes.c_void_p, + ctypes.POINTER(_UniffiRustCallStatus), +) +_UniffiLib.uniffi_glsdk_fn_method_node_get_info.restype = _UniffiRustBuffer +_UniffiLib.uniffi_glsdk_fn_method_node_list_funds.argtypes = ( + ctypes.c_void_p, + ctypes.POINTER(_UniffiRustCallStatus), +) +_UniffiLib.uniffi_glsdk_fn_method_node_list_funds.restype = _UniffiRustBuffer +_UniffiLib.uniffi_glsdk_fn_method_node_list_peer_channels.argtypes = ( + ctypes.c_void_p, + ctypes.POINTER(_UniffiRustCallStatus), +) +_UniffiLib.uniffi_glsdk_fn_method_node_list_peer_channels.restype = _UniffiRustBuffer +_UniffiLib.uniffi_glsdk_fn_method_node_list_peers.argtypes = ( + ctypes.c_void_p, + ctypes.POINTER(_UniffiRustCallStatus), +) +_UniffiLib.uniffi_glsdk_fn_method_node_list_peers.restype = _UniffiRustBuffer +_UniffiLib.uniffi_glsdk_fn_method_node_onchain_receive.argtypes = ( + ctypes.c_void_p, + ctypes.POINTER(_UniffiRustCallStatus), +) +_UniffiLib.uniffi_glsdk_fn_method_node_onchain_receive.restype = _UniffiRustBuffer +_UniffiLib.uniffi_glsdk_fn_method_node_onchain_send.argtypes = ( + ctypes.c_void_p, + _UniffiRustBuffer, + _UniffiRustBuffer, + ctypes.POINTER(_UniffiRustCallStatus), +) +_UniffiLib.uniffi_glsdk_fn_method_node_onchain_send.restype = _UniffiRustBuffer +_UniffiLib.uniffi_glsdk_fn_method_node_receive.argtypes = ( + ctypes.c_void_p, + _UniffiRustBuffer, + _UniffiRustBuffer, + _UniffiRustBuffer, + ctypes.POINTER(_UniffiRustCallStatus), +) +_UniffiLib.uniffi_glsdk_fn_method_node_receive.restype = _UniffiRustBuffer +_UniffiLib.uniffi_glsdk_fn_method_node_send.argtypes = ( + ctypes.c_void_p, + _UniffiRustBuffer, + _UniffiRustBuffer, + ctypes.POINTER(_UniffiRustCallStatus), +) +_UniffiLib.uniffi_glsdk_fn_method_node_send.restype = _UniffiRustBuffer +_UniffiLib.uniffi_glsdk_fn_method_node_stop.argtypes = ( + ctypes.c_void_p, + ctypes.POINTER(_UniffiRustCallStatus), +) +_UniffiLib.uniffi_glsdk_fn_method_node_stop.restype = None +_UniffiLib.uniffi_glsdk_fn_method_node_stream_node_events.argtypes = ( + ctypes.c_void_p, + ctypes.POINTER(_UniffiRustCallStatus), +) +_UniffiLib.uniffi_glsdk_fn_method_node_stream_node_events.restype = ctypes.c_void_p +_UniffiLib.uniffi_glsdk_fn_clone_nodeeventstream.argtypes = ( + ctypes.c_void_p, + ctypes.POINTER(_UniffiRustCallStatus), +) +_UniffiLib.uniffi_glsdk_fn_clone_nodeeventstream.restype = ctypes.c_void_p +_UniffiLib.uniffi_glsdk_fn_free_nodeeventstream.argtypes = ( + ctypes.c_void_p, + ctypes.POINTER(_UniffiRustCallStatus), +) +_UniffiLib.uniffi_glsdk_fn_free_nodeeventstream.restype = None +_UniffiLib.uniffi_glsdk_fn_method_nodeeventstream_next.argtypes = ( + ctypes.c_void_p, + ctypes.POINTER(_UniffiRustCallStatus), +) +_UniffiLib.uniffi_glsdk_fn_method_nodeeventstream_next.restype = _UniffiRustBuffer _UniffiLib.uniffi_glsdk_fn_clone_scheduler.argtypes = ( ctypes.c_void_p, ctypes.POINTER(_UniffiRustCallStatus), @@ -958,9 +1059,45 @@ class _UniffiForeignFutureStructVoid(ctypes.Structure): ctypes.POINTER(_UniffiRustCallStatus), ) _UniffiLib.ffi_glsdk_rust_future_complete_void.restype = None +_UniffiLib.uniffi_glsdk_checksum_method_credentials_save.argtypes = ( +) +_UniffiLib.uniffi_glsdk_checksum_method_credentials_save.restype = ctypes.c_uint16 _UniffiLib.uniffi_glsdk_checksum_method_handle_stop.argtypes = ( ) _UniffiLib.uniffi_glsdk_checksum_method_handle_stop.restype = ctypes.c_uint16 +_UniffiLib.uniffi_glsdk_checksum_method_node_get_info.argtypes = ( +) +_UniffiLib.uniffi_glsdk_checksum_method_node_get_info.restype = ctypes.c_uint16 +_UniffiLib.uniffi_glsdk_checksum_method_node_list_funds.argtypes = ( +) +_UniffiLib.uniffi_glsdk_checksum_method_node_list_funds.restype = ctypes.c_uint16 +_UniffiLib.uniffi_glsdk_checksum_method_node_list_peer_channels.argtypes = ( +) +_UniffiLib.uniffi_glsdk_checksum_method_node_list_peer_channels.restype = ctypes.c_uint16 +_UniffiLib.uniffi_glsdk_checksum_method_node_list_peers.argtypes = ( +) +_UniffiLib.uniffi_glsdk_checksum_method_node_list_peers.restype = ctypes.c_uint16 +_UniffiLib.uniffi_glsdk_checksum_method_node_onchain_receive.argtypes = ( +) +_UniffiLib.uniffi_glsdk_checksum_method_node_onchain_receive.restype = ctypes.c_uint16 +_UniffiLib.uniffi_glsdk_checksum_method_node_onchain_send.argtypes = ( +) +_UniffiLib.uniffi_glsdk_checksum_method_node_onchain_send.restype = ctypes.c_uint16 +_UniffiLib.uniffi_glsdk_checksum_method_node_receive.argtypes = ( +) +_UniffiLib.uniffi_glsdk_checksum_method_node_receive.restype = ctypes.c_uint16 +_UniffiLib.uniffi_glsdk_checksum_method_node_send.argtypes = ( +) +_UniffiLib.uniffi_glsdk_checksum_method_node_send.restype = ctypes.c_uint16 +_UniffiLib.uniffi_glsdk_checksum_method_node_stop.argtypes = ( +) +_UniffiLib.uniffi_glsdk_checksum_method_node_stop.restype = ctypes.c_uint16 +_UniffiLib.uniffi_glsdk_checksum_method_node_stream_node_events.argtypes = ( +) +_UniffiLib.uniffi_glsdk_checksum_method_node_stream_node_events.restype = ctypes.c_uint16 +_UniffiLib.uniffi_glsdk_checksum_method_nodeeventstream_next.argtypes = ( +) +_UniffiLib.uniffi_glsdk_checksum_method_nodeeventstream_next.restype = ctypes.c_uint16 _UniffiLib.uniffi_glsdk_checksum_method_scheduler_recover.argtypes = ( ) _UniffiLib.uniffi_glsdk_checksum_method_scheduler_recover.restype = ctypes.c_uint16 @@ -998,6 +1135,53 @@ class _UniffiForeignFutureStructVoid(ctypes.Structure): # Public interface members begin here. +class _UniffiConverterUInt32(_UniffiConverterPrimitiveInt): + CLASS_NAME = "u32" + VALUE_MIN = 0 + VALUE_MAX = 2**32 + + @staticmethod + def read(buf): + return buf.read_u32() + + @staticmethod + def write(value, buf): + buf.write_u32(value) + +class _UniffiConverterUInt64(_UniffiConverterPrimitiveInt): + CLASS_NAME = "u64" + VALUE_MIN = 0 + VALUE_MAX = 2**64 + + @staticmethod + def read(buf): + return buf.read_u64() + + @staticmethod + def write(value, buf): + buf.write_u64(value) + +class _UniffiConverterBool: + @classmethod + def check_lower(cls, value): + return not not value + + @classmethod + def lower(cls, value): + return 1 if value else 0 + + @staticmethod + def lift(value): + return value != 0 + + @classmethod + def read(cls, buf): + return cls.lift(buf.read_u8()) + + @classmethod + def write(cls, value, buf): + buf.write_u8(value) + class _UniffiConverterString: @staticmethod def check_lower(value): @@ -1061,202 +1245,1582 @@ def write(value, buf): -# Error -# We want to define each variant as a nested class that's also a subclass, -# which is tricky in Python. To accomplish this we're going to create each -# class separately, then manually add the child classes to the base class's -# __dict__. All of this happens in dummy class to avoid polluting the module -# namespace. -class Error(Exception): - pass - -_UniffiTempError = Error - -class Error: # type: ignore - class DuplicateNode(_UniffiTempError): - def __init__(self, *values): - if len(values) != 1: - raise TypeError(f"Expected 1 arguments, found {len(values)}") - if not isinstance(values[0], str): - raise TypeError(f"unexpected type for tuple element 0 - expected 'str', got '{type(values[0])}'") - super().__init__(", ".join(map(repr, values))) - self._values = values - - def __getitem__(self, index): - return self._values[index] - - def __repr__(self): - return "Error.DuplicateNode({})".format(str(self)) - _UniffiTempError.DuplicateNode = DuplicateNode # type: ignore - class NoSuchNode(_UniffiTempError): - def __init__(self, *values): - if len(values) != 1: - raise TypeError(f"Expected 1 arguments, found {len(values)}") - if not isinstance(values[0], str): - raise TypeError(f"unexpected type for tuple element 0 - expected 'str', got '{type(values[0])}'") - super().__init__(", ".join(map(repr, values))) - self._values = values - def __getitem__(self, index): - return self._values[index] - def __repr__(self): - return "Error.NoSuchNode({})".format(str(self)) - _UniffiTempError.NoSuchNode = NoSuchNode # type: ignore - class UnparseableCreds(_UniffiTempError): - def __init__(self): - pass +class FundChannel: + peer_id: "bytes" + our_amount_msat: "int" + amount_msat: "int" + funding_txid: "bytes" + funding_output: "int" + connected: "bool" + state: "ChannelState" + short_channel_id: "typing.Optional[str]" + channel_id: "typing.Optional[bytes]" + def __init__(self, *, peer_id: "bytes", our_amount_msat: "int", amount_msat: "int", funding_txid: "bytes", funding_output: "int", connected: "bool", state: "ChannelState", short_channel_id: "typing.Optional[str]", channel_id: "typing.Optional[bytes]"): + self.peer_id = peer_id + self.our_amount_msat = our_amount_msat + self.amount_msat = amount_msat + self.funding_txid = funding_txid + self.funding_output = funding_output + self.connected = connected + self.state = state + self.short_channel_id = short_channel_id + self.channel_id = channel_id - def __repr__(self): - return "Error.UnparseableCreds({})".format(str(self)) - _UniffiTempError.UnparseableCreds = UnparseableCreds # type: ignore - class PhraseCorrupted(_UniffiTempError): - def __init__(self): - pass + def __str__(self): + return "FundChannel(peer_id={}, our_amount_msat={}, amount_msat={}, funding_txid={}, funding_output={}, connected={}, state={}, short_channel_id={}, channel_id={})".format(self.peer_id, self.our_amount_msat, self.amount_msat, self.funding_txid, self.funding_output, self.connected, self.state, self.short_channel_id, self.channel_id) + + def __eq__(self, other): + if self.peer_id != other.peer_id: + return False + if self.our_amount_msat != other.our_amount_msat: + return False + if self.amount_msat != other.amount_msat: + return False + if self.funding_txid != other.funding_txid: + return False + if self.funding_output != other.funding_output: + return False + if self.connected != other.connected: + return False + if self.state != other.state: + return False + if self.short_channel_id != other.short_channel_id: + return False + if self.channel_id != other.channel_id: + return False + return True + +class _UniffiConverterTypeFundChannel(_UniffiConverterRustBuffer): + @staticmethod + def read(buf): + return FundChannel( + peer_id=_UniffiConverterBytes.read(buf), + our_amount_msat=_UniffiConverterUInt64.read(buf), + amount_msat=_UniffiConverterUInt64.read(buf), + funding_txid=_UniffiConverterBytes.read(buf), + funding_output=_UniffiConverterUInt32.read(buf), + connected=_UniffiConverterBool.read(buf), + state=_UniffiConverterTypeChannelState.read(buf), + short_channel_id=_UniffiConverterOptionalString.read(buf), + channel_id=_UniffiConverterOptionalBytes.read(buf), + ) - def __repr__(self): - return "Error.PhraseCorrupted({})".format(str(self)) - _UniffiTempError.PhraseCorrupted = PhraseCorrupted # type: ignore - class Other(_UniffiTempError): - def __init__(self, *values): - if len(values) != 1: - raise TypeError(f"Expected 1 arguments, found {len(values)}") - if not isinstance(values[0], str): - raise TypeError(f"unexpected type for tuple element 0 - expected 'str', got '{type(values[0])}'") - super().__init__(", ".join(map(repr, values))) - self._values = values + @staticmethod + def check_lower(value): + _UniffiConverterBytes.check_lower(value.peer_id) + _UniffiConverterUInt64.check_lower(value.our_amount_msat) + _UniffiConverterUInt64.check_lower(value.amount_msat) + _UniffiConverterBytes.check_lower(value.funding_txid) + _UniffiConverterUInt32.check_lower(value.funding_output) + _UniffiConverterBool.check_lower(value.connected) + _UniffiConverterTypeChannelState.check_lower(value.state) + _UniffiConverterOptionalString.check_lower(value.short_channel_id) + _UniffiConverterOptionalBytes.check_lower(value.channel_id) - def __getitem__(self, index): - return self._values[index] + @staticmethod + def write(value, buf): + _UniffiConverterBytes.write(value.peer_id, buf) + _UniffiConverterUInt64.write(value.our_amount_msat, buf) + _UniffiConverterUInt64.write(value.amount_msat, buf) + _UniffiConverterBytes.write(value.funding_txid, buf) + _UniffiConverterUInt32.write(value.funding_output, buf) + _UniffiConverterBool.write(value.connected, buf) + _UniffiConverterTypeChannelState.write(value.state, buf) + _UniffiConverterOptionalString.write(value.short_channel_id, buf) + _UniffiConverterOptionalBytes.write(value.channel_id, buf) + + +class FundOutput: + txid: "bytes" + output: "int" + amount_msat: "int" + status: "OutputStatus" + address: "typing.Optional[str]" + blockheight: "typing.Optional[int]" + def __init__(self, *, txid: "bytes", output: "int", amount_msat: "int", status: "OutputStatus", address: "typing.Optional[str]", blockheight: "typing.Optional[int]"): + self.txid = txid + self.output = output + self.amount_msat = amount_msat + self.status = status + self.address = address + self.blockheight = blockheight - def __repr__(self): - return "Error.Other({})".format(str(self)) - _UniffiTempError.Other = Other # type: ignore + def __str__(self): + return "FundOutput(txid={}, output={}, amount_msat={}, status={}, address={}, blockheight={})".format(self.txid, self.output, self.amount_msat, self.status, self.address, self.blockheight) + + def __eq__(self, other): + if self.txid != other.txid: + return False + if self.output != other.output: + return False + if self.amount_msat != other.amount_msat: + return False + if self.status != other.status: + return False + if self.address != other.address: + return False + if self.blockheight != other.blockheight: + return False + return True + +class _UniffiConverterTypeFundOutput(_UniffiConverterRustBuffer): + @staticmethod + def read(buf): + return FundOutput( + txid=_UniffiConverterBytes.read(buf), + output=_UniffiConverterUInt32.read(buf), + amount_msat=_UniffiConverterUInt64.read(buf), + status=_UniffiConverterTypeOutputStatus.read(buf), + address=_UniffiConverterOptionalString.read(buf), + blockheight=_UniffiConverterOptionalUInt32.read(buf), + ) -Error = _UniffiTempError # type: ignore -del _UniffiTempError + @staticmethod + def check_lower(value): + _UniffiConverterBytes.check_lower(value.txid) + _UniffiConverterUInt32.check_lower(value.output) + _UniffiConverterUInt64.check_lower(value.amount_msat) + _UniffiConverterTypeOutputStatus.check_lower(value.status) + _UniffiConverterOptionalString.check_lower(value.address) + _UniffiConverterOptionalUInt32.check_lower(value.blockheight) + @staticmethod + def write(value, buf): + _UniffiConverterBytes.write(value.txid, buf) + _UniffiConverterUInt32.write(value.output, buf) + _UniffiConverterUInt64.write(value.amount_msat, buf) + _UniffiConverterTypeOutputStatus.write(value.status, buf) + _UniffiConverterOptionalString.write(value.address, buf) + _UniffiConverterOptionalUInt32.write(value.blockheight, buf) + + +class GetInfoResponse: + id: "bytes" + alias: "typing.Optional[str]" + color: "bytes" + num_peers: "int" + num_pending_channels: "int" + num_active_channels: "int" + num_inactive_channels: "int" + version: "str" + lightning_dir: "str" + blockheight: "int" + network: "str" + fees_collected_msat: "int" + def __init__(self, *, id: "bytes", alias: "typing.Optional[str]", color: "bytes", num_peers: "int", num_pending_channels: "int", num_active_channels: "int", num_inactive_channels: "int", version: "str", lightning_dir: "str", blockheight: "int", network: "str", fees_collected_msat: "int"): + self.id = id + self.alias = alias + self.color = color + self.num_peers = num_peers + self.num_pending_channels = num_pending_channels + self.num_active_channels = num_active_channels + self.num_inactive_channels = num_inactive_channels + self.version = version + self.lightning_dir = lightning_dir + self.blockheight = blockheight + self.network = network + self.fees_collected_msat = fees_collected_msat -class _UniffiConverterTypeError(_UniffiConverterRustBuffer): + def __str__(self): + return "GetInfoResponse(id={}, alias={}, color={}, num_peers={}, num_pending_channels={}, num_active_channels={}, num_inactive_channels={}, version={}, lightning_dir={}, blockheight={}, network={}, fees_collected_msat={})".format(self.id, self.alias, self.color, self.num_peers, self.num_pending_channels, self.num_active_channels, self.num_inactive_channels, self.version, self.lightning_dir, self.blockheight, self.network, self.fees_collected_msat) + + def __eq__(self, other): + if self.id != other.id: + return False + if self.alias != other.alias: + return False + if self.color != other.color: + return False + if self.num_peers != other.num_peers: + return False + if self.num_pending_channels != other.num_pending_channels: + return False + if self.num_active_channels != other.num_active_channels: + return False + if self.num_inactive_channels != other.num_inactive_channels: + return False + if self.version != other.version: + return False + if self.lightning_dir != other.lightning_dir: + return False + if self.blockheight != other.blockheight: + return False + if self.network != other.network: + return False + if self.fees_collected_msat != other.fees_collected_msat: + return False + return True + +class _UniffiConverterTypeGetInfoResponse(_UniffiConverterRustBuffer): @staticmethod def read(buf): - variant = buf.read_i32() - if variant == 1: - return Error.DuplicateNode( - _UniffiConverterString.read(buf), - ) - if variant == 2: - return Error.NoSuchNode( - _UniffiConverterString.read(buf), - ) - if variant == 3: - return Error.UnparseableCreds( - ) - if variant == 4: - return Error.PhraseCorrupted( - ) - if variant == 5: - return Error.Other( - _UniffiConverterString.read(buf), - ) - raise InternalError("Raw enum value doesn't match any cases") + return GetInfoResponse( + id=_UniffiConverterBytes.read(buf), + alias=_UniffiConverterOptionalString.read(buf), + color=_UniffiConverterBytes.read(buf), + num_peers=_UniffiConverterUInt32.read(buf), + num_pending_channels=_UniffiConverterUInt32.read(buf), + num_active_channels=_UniffiConverterUInt32.read(buf), + num_inactive_channels=_UniffiConverterUInt32.read(buf), + version=_UniffiConverterString.read(buf), + lightning_dir=_UniffiConverterString.read(buf), + blockheight=_UniffiConverterUInt32.read(buf), + network=_UniffiConverterString.read(buf), + fees_collected_msat=_UniffiConverterUInt64.read(buf), + ) @staticmethod def check_lower(value): - if isinstance(value, Error.DuplicateNode): - _UniffiConverterString.check_lower(value._values[0]) - return - if isinstance(value, Error.NoSuchNode): - _UniffiConverterString.check_lower(value._values[0]) - return - if isinstance(value, Error.UnparseableCreds): - return - if isinstance(value, Error.PhraseCorrupted): - return - if isinstance(value, Error.Other): - _UniffiConverterString.check_lower(value._values[0]) - return + _UniffiConverterBytes.check_lower(value.id) + _UniffiConverterOptionalString.check_lower(value.alias) + _UniffiConverterBytes.check_lower(value.color) + _UniffiConverterUInt32.check_lower(value.num_peers) + _UniffiConverterUInt32.check_lower(value.num_pending_channels) + _UniffiConverterUInt32.check_lower(value.num_active_channels) + _UniffiConverterUInt32.check_lower(value.num_inactive_channels) + _UniffiConverterString.check_lower(value.version) + _UniffiConverterString.check_lower(value.lightning_dir) + _UniffiConverterUInt32.check_lower(value.blockheight) + _UniffiConverterString.check_lower(value.network) + _UniffiConverterUInt64.check_lower(value.fees_collected_msat) @staticmethod def write(value, buf): - if isinstance(value, Error.DuplicateNode): - buf.write_i32(1) - _UniffiConverterString.write(value._values[0], buf) - if isinstance(value, Error.NoSuchNode): - buf.write_i32(2) - _UniffiConverterString.write(value._values[0], buf) - if isinstance(value, Error.UnparseableCreds): - buf.write_i32(3) - if isinstance(value, Error.PhraseCorrupted): - buf.write_i32(4) - if isinstance(value, Error.Other): - buf.write_i32(5) - _UniffiConverterString.write(value._values[0], buf) + _UniffiConverterBytes.write(value.id, buf) + _UniffiConverterOptionalString.write(value.alias, buf) + _UniffiConverterBytes.write(value.color, buf) + _UniffiConverterUInt32.write(value.num_peers, buf) + _UniffiConverterUInt32.write(value.num_pending_channels, buf) + _UniffiConverterUInt32.write(value.num_active_channels, buf) + _UniffiConverterUInt32.write(value.num_inactive_channels, buf) + _UniffiConverterString.write(value.version, buf) + _UniffiConverterString.write(value.lightning_dir, buf) + _UniffiConverterUInt32.write(value.blockheight, buf) + _UniffiConverterString.write(value.network, buf) + _UniffiConverterUInt64.write(value.fees_collected_msat, buf) + + +class InvoicePaidEvent: + """ + Details of a paid invoice. + """ + payment_hash: "bytes" + """ + The payment hash of the paid invoice. + """ + bolt11: "str" + """ + The bolt11 invoice string. + """ + preimage: "bytes" + """ + The preimage that proves payment. + """ + label: "str" + """ + The label assigned to the invoice. + """ -class Network(enum.Enum): - BITCOIN = 0 - - REGTEST = 1 - + amount_msat: "int" + """ + Amount received in millisatoshis. + """ + def __init__(self, *, payment_hash: "bytes", bolt11: "str", preimage: "bytes", label: "str", amount_msat: "int"): + self.payment_hash = payment_hash + self.bolt11 = bolt11 + self.preimage = preimage + self.label = label + self.amount_msat = amount_msat -class _UniffiConverterTypeNetwork(_UniffiConverterRustBuffer): + def __str__(self): + return "InvoicePaidEvent(payment_hash={}, bolt11={}, preimage={}, label={}, amount_msat={})".format(self.payment_hash, self.bolt11, self.preimage, self.label, self.amount_msat) + + def __eq__(self, other): + if self.payment_hash != other.payment_hash: + return False + if self.bolt11 != other.bolt11: + return False + if self.preimage != other.preimage: + return False + if self.label != other.label: + return False + if self.amount_msat != other.amount_msat: + return False + return True + +class _UniffiConverterTypeInvoicePaidEvent(_UniffiConverterRustBuffer): @staticmethod def read(buf): - variant = buf.read_i32() - if variant == 1: - return Network.BITCOIN - if variant == 2: + return InvoicePaidEvent( + payment_hash=_UniffiConverterBytes.read(buf), + bolt11=_UniffiConverterString.read(buf), + preimage=_UniffiConverterBytes.read(buf), + label=_UniffiConverterString.read(buf), + amount_msat=_UniffiConverterUInt64.read(buf), + ) + + @staticmethod + def check_lower(value): + _UniffiConverterBytes.check_lower(value.payment_hash) + _UniffiConverterString.check_lower(value.bolt11) + _UniffiConverterBytes.check_lower(value.preimage) + _UniffiConverterString.check_lower(value.label) + _UniffiConverterUInt64.check_lower(value.amount_msat) + + @staticmethod + def write(value, buf): + _UniffiConverterBytes.write(value.payment_hash, buf) + _UniffiConverterString.write(value.bolt11, buf) + _UniffiConverterBytes.write(value.preimage, buf) + _UniffiConverterString.write(value.label, buf) + _UniffiConverterUInt64.write(value.amount_msat, buf) + + +class ListFundsResponse: + outputs: "typing.List[FundOutput]" + channels: "typing.List[FundChannel]" + def __init__(self, *, outputs: "typing.List[FundOutput]", channels: "typing.List[FundChannel]"): + self.outputs = outputs + self.channels = channels + + def __str__(self): + return "ListFundsResponse(outputs={}, channels={})".format(self.outputs, self.channels) + + def __eq__(self, other): + if self.outputs != other.outputs: + return False + if self.channels != other.channels: + return False + return True + +class _UniffiConverterTypeListFundsResponse(_UniffiConverterRustBuffer): + @staticmethod + def read(buf): + return ListFundsResponse( + outputs=_UniffiConverterSequenceTypeFundOutput.read(buf), + channels=_UniffiConverterSequenceTypeFundChannel.read(buf), + ) + + @staticmethod + def check_lower(value): + _UniffiConverterSequenceTypeFundOutput.check_lower(value.outputs) + _UniffiConverterSequenceTypeFundChannel.check_lower(value.channels) + + @staticmethod + def write(value, buf): + _UniffiConverterSequenceTypeFundOutput.write(value.outputs, buf) + _UniffiConverterSequenceTypeFundChannel.write(value.channels, buf) + + +class ListPeerChannelsResponse: + channels: "typing.List[PeerChannel]" + def __init__(self, *, channels: "typing.List[PeerChannel]"): + self.channels = channels + + def __str__(self): + return "ListPeerChannelsResponse(channels={})".format(self.channels) + + def __eq__(self, other): + if self.channels != other.channels: + return False + return True + +class _UniffiConverterTypeListPeerChannelsResponse(_UniffiConverterRustBuffer): + @staticmethod + def read(buf): + return ListPeerChannelsResponse( + channels=_UniffiConverterSequenceTypePeerChannel.read(buf), + ) + + @staticmethod + def check_lower(value): + _UniffiConverterSequenceTypePeerChannel.check_lower(value.channels) + + @staticmethod + def write(value, buf): + _UniffiConverterSequenceTypePeerChannel.write(value.channels, buf) + + +class ListPeersResponse: + peers: "typing.List[Peer]" + def __init__(self, *, peers: "typing.List[Peer]"): + self.peers = peers + + def __str__(self): + return "ListPeersResponse(peers={})".format(self.peers) + + def __eq__(self, other): + if self.peers != other.peers: + return False + return True + +class _UniffiConverterTypeListPeersResponse(_UniffiConverterRustBuffer): + @staticmethod + def read(buf): + return ListPeersResponse( + peers=_UniffiConverterSequenceTypePeer.read(buf), + ) + + @staticmethod + def check_lower(value): + _UniffiConverterSequenceTypePeer.check_lower(value.peers) + + @staticmethod + def write(value, buf): + _UniffiConverterSequenceTypePeer.write(value.peers, buf) + + +class OnchainReceiveResponse: + bech32: "str" + p2tr: "str" + def __init__(self, *, bech32: "str", p2tr: "str"): + self.bech32 = bech32 + self.p2tr = p2tr + + def __str__(self): + return "OnchainReceiveResponse(bech32={}, p2tr={})".format(self.bech32, self.p2tr) + + def __eq__(self, other): + if self.bech32 != other.bech32: + return False + if self.p2tr != other.p2tr: + return False + return True + +class _UniffiConverterTypeOnchainReceiveResponse(_UniffiConverterRustBuffer): + @staticmethod + def read(buf): + return OnchainReceiveResponse( + bech32=_UniffiConverterString.read(buf), + p2tr=_UniffiConverterString.read(buf), + ) + + @staticmethod + def check_lower(value): + _UniffiConverterString.check_lower(value.bech32) + _UniffiConverterString.check_lower(value.p2tr) + + @staticmethod + def write(value, buf): + _UniffiConverterString.write(value.bech32, buf) + _UniffiConverterString.write(value.p2tr, buf) + + +class OnchainSendResponse: + tx: "bytes" + txid: "bytes" + psbt: "str" + def __init__(self, *, tx: "bytes", txid: "bytes", psbt: "str"): + self.tx = tx + self.txid = txid + self.psbt = psbt + + def __str__(self): + return "OnchainSendResponse(tx={}, txid={}, psbt={})".format(self.tx, self.txid, self.psbt) + + def __eq__(self, other): + if self.tx != other.tx: + return False + if self.txid != other.txid: + return False + if self.psbt != other.psbt: + return False + return True + +class _UniffiConverterTypeOnchainSendResponse(_UniffiConverterRustBuffer): + @staticmethod + def read(buf): + return OnchainSendResponse( + tx=_UniffiConverterBytes.read(buf), + txid=_UniffiConverterBytes.read(buf), + psbt=_UniffiConverterString.read(buf), + ) + + @staticmethod + def check_lower(value): + _UniffiConverterBytes.check_lower(value.tx) + _UniffiConverterBytes.check_lower(value.txid) + _UniffiConverterString.check_lower(value.psbt) + + @staticmethod + def write(value, buf): + _UniffiConverterBytes.write(value.tx, buf) + _UniffiConverterBytes.write(value.txid, buf) + _UniffiConverterString.write(value.psbt, buf) + + +class Peer: + id: "bytes" + connected: "bool" + num_channels: "typing.Optional[int]" + netaddr: "typing.List[str]" + remote_addr: "typing.Optional[str]" + features: "typing.Optional[bytes]" + def __init__(self, *, id: "bytes", connected: "bool", num_channels: "typing.Optional[int]", netaddr: "typing.List[str]", remote_addr: "typing.Optional[str]", features: "typing.Optional[bytes]"): + self.id = id + self.connected = connected + self.num_channels = num_channels + self.netaddr = netaddr + self.remote_addr = remote_addr + self.features = features + + def __str__(self): + return "Peer(id={}, connected={}, num_channels={}, netaddr={}, remote_addr={}, features={})".format(self.id, self.connected, self.num_channels, self.netaddr, self.remote_addr, self.features) + + def __eq__(self, other): + if self.id != other.id: + return False + if self.connected != other.connected: + return False + if self.num_channels != other.num_channels: + return False + if self.netaddr != other.netaddr: + return False + if self.remote_addr != other.remote_addr: + return False + if self.features != other.features: + return False + return True + +class _UniffiConverterTypePeer(_UniffiConverterRustBuffer): + @staticmethod + def read(buf): + return Peer( + id=_UniffiConverterBytes.read(buf), + connected=_UniffiConverterBool.read(buf), + num_channels=_UniffiConverterOptionalUInt32.read(buf), + netaddr=_UniffiConverterSequenceString.read(buf), + remote_addr=_UniffiConverterOptionalString.read(buf), + features=_UniffiConverterOptionalBytes.read(buf), + ) + + @staticmethod + def check_lower(value): + _UniffiConverterBytes.check_lower(value.id) + _UniffiConverterBool.check_lower(value.connected) + _UniffiConverterOptionalUInt32.check_lower(value.num_channels) + _UniffiConverterSequenceString.check_lower(value.netaddr) + _UniffiConverterOptionalString.check_lower(value.remote_addr) + _UniffiConverterOptionalBytes.check_lower(value.features) + + @staticmethod + def write(value, buf): + _UniffiConverterBytes.write(value.id, buf) + _UniffiConverterBool.write(value.connected, buf) + _UniffiConverterOptionalUInt32.write(value.num_channels, buf) + _UniffiConverterSequenceString.write(value.netaddr, buf) + _UniffiConverterOptionalString.write(value.remote_addr, buf) + _UniffiConverterOptionalBytes.write(value.features, buf) + + +class PeerChannel: + peer_id: "bytes" + peer_connected: "bool" + state: "ChannelState" + short_channel_id: "typing.Optional[str]" + channel_id: "typing.Optional[bytes]" + funding_txid: "typing.Optional[bytes]" + funding_outnum: "typing.Optional[int]" + to_us_msat: "typing.Optional[int]" + total_msat: "typing.Optional[int]" + spendable_msat: "typing.Optional[int]" + receivable_msat: "typing.Optional[int]" + def __init__(self, *, peer_id: "bytes", peer_connected: "bool", state: "ChannelState", short_channel_id: "typing.Optional[str]", channel_id: "typing.Optional[bytes]", funding_txid: "typing.Optional[bytes]", funding_outnum: "typing.Optional[int]", to_us_msat: "typing.Optional[int]", total_msat: "typing.Optional[int]", spendable_msat: "typing.Optional[int]", receivable_msat: "typing.Optional[int]"): + self.peer_id = peer_id + self.peer_connected = peer_connected + self.state = state + self.short_channel_id = short_channel_id + self.channel_id = channel_id + self.funding_txid = funding_txid + self.funding_outnum = funding_outnum + self.to_us_msat = to_us_msat + self.total_msat = total_msat + self.spendable_msat = spendable_msat + self.receivable_msat = receivable_msat + + def __str__(self): + return "PeerChannel(peer_id={}, peer_connected={}, state={}, short_channel_id={}, channel_id={}, funding_txid={}, funding_outnum={}, to_us_msat={}, total_msat={}, spendable_msat={}, receivable_msat={})".format(self.peer_id, self.peer_connected, self.state, self.short_channel_id, self.channel_id, self.funding_txid, self.funding_outnum, self.to_us_msat, self.total_msat, self.spendable_msat, self.receivable_msat) + + def __eq__(self, other): + if self.peer_id != other.peer_id: + return False + if self.peer_connected != other.peer_connected: + return False + if self.state != other.state: + return False + if self.short_channel_id != other.short_channel_id: + return False + if self.channel_id != other.channel_id: + return False + if self.funding_txid != other.funding_txid: + return False + if self.funding_outnum != other.funding_outnum: + return False + if self.to_us_msat != other.to_us_msat: + return False + if self.total_msat != other.total_msat: + return False + if self.spendable_msat != other.spendable_msat: + return False + if self.receivable_msat != other.receivable_msat: + return False + return True + +class _UniffiConverterTypePeerChannel(_UniffiConverterRustBuffer): + @staticmethod + def read(buf): + return PeerChannel( + peer_id=_UniffiConverterBytes.read(buf), + peer_connected=_UniffiConverterBool.read(buf), + state=_UniffiConverterTypeChannelState.read(buf), + short_channel_id=_UniffiConverterOptionalString.read(buf), + channel_id=_UniffiConverterOptionalBytes.read(buf), + funding_txid=_UniffiConverterOptionalBytes.read(buf), + funding_outnum=_UniffiConverterOptionalUInt32.read(buf), + to_us_msat=_UniffiConverterOptionalUInt64.read(buf), + total_msat=_UniffiConverterOptionalUInt64.read(buf), + spendable_msat=_UniffiConverterOptionalUInt64.read(buf), + receivable_msat=_UniffiConverterOptionalUInt64.read(buf), + ) + + @staticmethod + def check_lower(value): + _UniffiConverterBytes.check_lower(value.peer_id) + _UniffiConverterBool.check_lower(value.peer_connected) + _UniffiConverterTypeChannelState.check_lower(value.state) + _UniffiConverterOptionalString.check_lower(value.short_channel_id) + _UniffiConverterOptionalBytes.check_lower(value.channel_id) + _UniffiConverterOptionalBytes.check_lower(value.funding_txid) + _UniffiConverterOptionalUInt32.check_lower(value.funding_outnum) + _UniffiConverterOptionalUInt64.check_lower(value.to_us_msat) + _UniffiConverterOptionalUInt64.check_lower(value.total_msat) + _UniffiConverterOptionalUInt64.check_lower(value.spendable_msat) + _UniffiConverterOptionalUInt64.check_lower(value.receivable_msat) + + @staticmethod + def write(value, buf): + _UniffiConverterBytes.write(value.peer_id, buf) + _UniffiConverterBool.write(value.peer_connected, buf) + _UniffiConverterTypeChannelState.write(value.state, buf) + _UniffiConverterOptionalString.write(value.short_channel_id, buf) + _UniffiConverterOptionalBytes.write(value.channel_id, buf) + _UniffiConverterOptionalBytes.write(value.funding_txid, buf) + _UniffiConverterOptionalUInt32.write(value.funding_outnum, buf) + _UniffiConverterOptionalUInt64.write(value.to_us_msat, buf) + _UniffiConverterOptionalUInt64.write(value.total_msat, buf) + _UniffiConverterOptionalUInt64.write(value.spendable_msat, buf) + _UniffiConverterOptionalUInt64.write(value.receivable_msat, buf) + + +class ReceiveResponse: + bolt11: "str" + def __init__(self, *, bolt11: "str"): + self.bolt11 = bolt11 + + def __str__(self): + return "ReceiveResponse(bolt11={})".format(self.bolt11) + + def __eq__(self, other): + if self.bolt11 != other.bolt11: + return False + return True + +class _UniffiConverterTypeReceiveResponse(_UniffiConverterRustBuffer): + @staticmethod + def read(buf): + return ReceiveResponse( + bolt11=_UniffiConverterString.read(buf), + ) + + @staticmethod + def check_lower(value): + _UniffiConverterString.check_lower(value.bolt11) + + @staticmethod + def write(value, buf): + _UniffiConverterString.write(value.bolt11, buf) + + +class SendResponse: + status: "PayStatus" + preimage: "bytes" + amount_msat: "int" + amount_sent_msat: "int" + parts: "int" + def __init__(self, *, status: "PayStatus", preimage: "bytes", amount_msat: "int", amount_sent_msat: "int", parts: "int"): + self.status = status + self.preimage = preimage + self.amount_msat = amount_msat + self.amount_sent_msat = amount_sent_msat + self.parts = parts + + def __str__(self): + return "SendResponse(status={}, preimage={}, amount_msat={}, amount_sent_msat={}, parts={})".format(self.status, self.preimage, self.amount_msat, self.amount_sent_msat, self.parts) + + def __eq__(self, other): + if self.status != other.status: + return False + if self.preimage != other.preimage: + return False + if self.amount_msat != other.amount_msat: + return False + if self.amount_sent_msat != other.amount_sent_msat: + return False + if self.parts != other.parts: + return False + return True + +class _UniffiConverterTypeSendResponse(_UniffiConverterRustBuffer): + @staticmethod + def read(buf): + return SendResponse( + status=_UniffiConverterTypePayStatus.read(buf), + preimage=_UniffiConverterBytes.read(buf), + amount_msat=_UniffiConverterUInt64.read(buf), + amount_sent_msat=_UniffiConverterUInt64.read(buf), + parts=_UniffiConverterUInt32.read(buf), + ) + + @staticmethod + def check_lower(value): + _UniffiConverterTypePayStatus.check_lower(value.status) + _UniffiConverterBytes.check_lower(value.preimage) + _UniffiConverterUInt64.check_lower(value.amount_msat) + _UniffiConverterUInt64.check_lower(value.amount_sent_msat) + _UniffiConverterUInt32.check_lower(value.parts) + + @staticmethod + def write(value, buf): + _UniffiConverterTypePayStatus.write(value.status, buf) + _UniffiConverterBytes.write(value.preimage, buf) + _UniffiConverterUInt64.write(value.amount_msat, buf) + _UniffiConverterUInt64.write(value.amount_sent_msat, buf) + _UniffiConverterUInt32.write(value.parts, buf) + + + + + +class ChannelState(enum.Enum): + OPENINGD = 0 + + CHANNELD_AWAITING_LOCKIN = 1 + + CHANNELD_NORMAL = 2 + + CHANNELD_SHUTTING_DOWN = 3 + + CLOSINGD_SIGEXCHANGE = 4 + + CLOSINGD_COMPLETE = 5 + + AWAITING_UNILATERAL = 6 + + FUNDING_SPEND_SEEN = 7 + + ONCHAIN = 8 + + DUALOPEND_OPEN_INIT = 9 + + DUALOPEND_AWAITING_LOCKIN = 10 + + DUALOPEND_OPEN_COMMITTED = 11 + + DUALOPEND_OPEN_COMMIT_READY = 12 + + + +class _UniffiConverterTypeChannelState(_UniffiConverterRustBuffer): + @staticmethod + def read(buf): + variant = buf.read_i32() + if variant == 1: + return ChannelState.OPENINGD + if variant == 2: + return ChannelState.CHANNELD_AWAITING_LOCKIN + if variant == 3: + return ChannelState.CHANNELD_NORMAL + if variant == 4: + return ChannelState.CHANNELD_SHUTTING_DOWN + if variant == 5: + return ChannelState.CLOSINGD_SIGEXCHANGE + if variant == 6: + return ChannelState.CLOSINGD_COMPLETE + if variant == 7: + return ChannelState.AWAITING_UNILATERAL + if variant == 8: + return ChannelState.FUNDING_SPEND_SEEN + if variant == 9: + return ChannelState.ONCHAIN + if variant == 10: + return ChannelState.DUALOPEND_OPEN_INIT + if variant == 11: + return ChannelState.DUALOPEND_AWAITING_LOCKIN + if variant == 12: + return ChannelState.DUALOPEND_OPEN_COMMITTED + if variant == 13: + return ChannelState.DUALOPEND_OPEN_COMMIT_READY + raise InternalError("Raw enum value doesn't match any cases") + + @staticmethod + def check_lower(value): + if value == ChannelState.OPENINGD: + return + if value == ChannelState.CHANNELD_AWAITING_LOCKIN: + return + if value == ChannelState.CHANNELD_NORMAL: + return + if value == ChannelState.CHANNELD_SHUTTING_DOWN: + return + if value == ChannelState.CLOSINGD_SIGEXCHANGE: + return + if value == ChannelState.CLOSINGD_COMPLETE: + return + if value == ChannelState.AWAITING_UNILATERAL: + return + if value == ChannelState.FUNDING_SPEND_SEEN: + return + if value == ChannelState.ONCHAIN: + return + if value == ChannelState.DUALOPEND_OPEN_INIT: + return + if value == ChannelState.DUALOPEND_AWAITING_LOCKIN: + return + if value == ChannelState.DUALOPEND_OPEN_COMMITTED: + return + if value == ChannelState.DUALOPEND_OPEN_COMMIT_READY: + return + raise ValueError(value) + + @staticmethod + def write(value, buf): + if value == ChannelState.OPENINGD: + buf.write_i32(1) + if value == ChannelState.CHANNELD_AWAITING_LOCKIN: + buf.write_i32(2) + if value == ChannelState.CHANNELD_NORMAL: + buf.write_i32(3) + if value == ChannelState.CHANNELD_SHUTTING_DOWN: + buf.write_i32(4) + if value == ChannelState.CLOSINGD_SIGEXCHANGE: + buf.write_i32(5) + if value == ChannelState.CLOSINGD_COMPLETE: + buf.write_i32(6) + if value == ChannelState.AWAITING_UNILATERAL: + buf.write_i32(7) + if value == ChannelState.FUNDING_SPEND_SEEN: + buf.write_i32(8) + if value == ChannelState.ONCHAIN: + buf.write_i32(9) + if value == ChannelState.DUALOPEND_OPEN_INIT: + buf.write_i32(10) + if value == ChannelState.DUALOPEND_AWAITING_LOCKIN: + buf.write_i32(11) + if value == ChannelState.DUALOPEND_OPEN_COMMITTED: + buf.write_i32(12) + if value == ChannelState.DUALOPEND_OPEN_COMMIT_READY: + buf.write_i32(13) + + + + +# Error +# We want to define each variant as a nested class that's also a subclass, +# which is tricky in Python. To accomplish this we're going to create each +# class separately, then manually add the child classes to the base class's +# __dict__. All of this happens in dummy class to avoid polluting the module +# namespace. +class Error(Exception): + pass + +_UniffiTempError = Error + +class Error: # type: ignore + class DuplicateNode(_UniffiTempError): + def __init__(self, *values): + if len(values) != 1: + raise TypeError(f"Expected 1 arguments, found {len(values)}") + if not isinstance(values[0], str): + raise TypeError(f"unexpected type for tuple element 0 - expected 'str', got '{type(values[0])}'") + super().__init__(", ".join(map(repr, values))) + self._values = values + + def __getitem__(self, index): + return self._values[index] + + def __repr__(self): + return "Error.DuplicateNode({})".format(str(self)) + _UniffiTempError.DuplicateNode = DuplicateNode # type: ignore + class NoSuchNode(_UniffiTempError): + def __init__(self, *values): + if len(values) != 1: + raise TypeError(f"Expected 1 arguments, found {len(values)}") + if not isinstance(values[0], str): + raise TypeError(f"unexpected type for tuple element 0 - expected 'str', got '{type(values[0])}'") + super().__init__(", ".join(map(repr, values))) + self._values = values + + def __getitem__(self, index): + return self._values[index] + + def __repr__(self): + return "Error.NoSuchNode({})".format(str(self)) + _UniffiTempError.NoSuchNode = NoSuchNode # type: ignore + class UnparseableCreds(_UniffiTempError): + def __init__(self): + pass + + def __repr__(self): + return "Error.UnparseableCreds({})".format(str(self)) + _UniffiTempError.UnparseableCreds = UnparseableCreds # type: ignore + class PhraseCorrupted(_UniffiTempError): + def __init__(self): + pass + + def __repr__(self): + return "Error.PhraseCorrupted({})".format(str(self)) + _UniffiTempError.PhraseCorrupted = PhraseCorrupted # type: ignore + class Rpc(_UniffiTempError): + def __init__(self, *values): + if len(values) != 1: + raise TypeError(f"Expected 1 arguments, found {len(values)}") + if not isinstance(values[0], str): + raise TypeError(f"unexpected type for tuple element 0 - expected 'str', got '{type(values[0])}'") + super().__init__(", ".join(map(repr, values))) + self._values = values + + def __getitem__(self, index): + return self._values[index] + + def __repr__(self): + return "Error.Rpc({})".format(str(self)) + _UniffiTempError.Rpc = Rpc # type: ignore + class Argument(_UniffiTempError): + def __init__(self, *values): + if len(values) != 2: + raise TypeError(f"Expected 2 arguments, found {len(values)}") + if not isinstance(values[0], str): + raise TypeError(f"unexpected type for tuple element 0 - expected 'str', got '{type(values[0])}'") + if not isinstance(values[1], str): + raise TypeError(f"unexpected type for tuple element 1 - expected 'str', got '{type(values[1])}'") + super().__init__(", ".join(map(repr, values))) + self._values = values + + def __getitem__(self, index): + return self._values[index] + + def __repr__(self): + return "Error.Argument({})".format(str(self)) + _UniffiTempError.Argument = Argument # type: ignore + class Other(_UniffiTempError): + def __init__(self, *values): + if len(values) != 1: + raise TypeError(f"Expected 1 arguments, found {len(values)}") + if not isinstance(values[0], str): + raise TypeError(f"unexpected type for tuple element 0 - expected 'str', got '{type(values[0])}'") + super().__init__(", ".join(map(repr, values))) + self._values = values + + def __getitem__(self, index): + return self._values[index] + + def __repr__(self): + return "Error.Other({})".format(str(self)) + _UniffiTempError.Other = Other # type: ignore + +Error = _UniffiTempError # type: ignore +del _UniffiTempError + + +class _UniffiConverterTypeError(_UniffiConverterRustBuffer): + @staticmethod + def read(buf): + variant = buf.read_i32() + if variant == 1: + return Error.DuplicateNode( + _UniffiConverterString.read(buf), + ) + if variant == 2: + return Error.NoSuchNode( + _UniffiConverterString.read(buf), + ) + if variant == 3: + return Error.UnparseableCreds( + ) + if variant == 4: + return Error.PhraseCorrupted( + ) + if variant == 5: + return Error.Rpc( + _UniffiConverterString.read(buf), + ) + if variant == 6: + return Error.Argument( + _UniffiConverterString.read(buf), + _UniffiConverterString.read(buf), + ) + if variant == 7: + return Error.Other( + _UniffiConverterString.read(buf), + ) + raise InternalError("Raw enum value doesn't match any cases") + + @staticmethod + def check_lower(value): + if isinstance(value, Error.DuplicateNode): + _UniffiConverterString.check_lower(value._values[0]) + return + if isinstance(value, Error.NoSuchNode): + _UniffiConverterString.check_lower(value._values[0]) + return + if isinstance(value, Error.UnparseableCreds): + return + if isinstance(value, Error.PhraseCorrupted): + return + if isinstance(value, Error.Rpc): + _UniffiConverterString.check_lower(value._values[0]) + return + if isinstance(value, Error.Argument): + _UniffiConverterString.check_lower(value._values[0]) + _UniffiConverterString.check_lower(value._values[1]) + return + if isinstance(value, Error.Other): + _UniffiConverterString.check_lower(value._values[0]) + return + + @staticmethod + def write(value, buf): + if isinstance(value, Error.DuplicateNode): + buf.write_i32(1) + _UniffiConverterString.write(value._values[0], buf) + if isinstance(value, Error.NoSuchNode): + buf.write_i32(2) + _UniffiConverterString.write(value._values[0], buf) + if isinstance(value, Error.UnparseableCreds): + buf.write_i32(3) + if isinstance(value, Error.PhraseCorrupted): + buf.write_i32(4) + if isinstance(value, Error.Rpc): + buf.write_i32(5) + _UniffiConverterString.write(value._values[0], buf) + if isinstance(value, Error.Argument): + buf.write_i32(6) + _UniffiConverterString.write(value._values[0], buf) + _UniffiConverterString.write(value._values[1], buf) + if isinstance(value, Error.Other): + buf.write_i32(7) + _UniffiConverterString.write(value._values[0], buf) + + + + + +class Network(enum.Enum): + BITCOIN = 0 + + REGTEST = 1 + + + +class _UniffiConverterTypeNetwork(_UniffiConverterRustBuffer): + @staticmethod + def read(buf): + variant = buf.read_i32() + if variant == 1: + return Network.BITCOIN + if variant == 2: return Network.REGTEST raise InternalError("Raw enum value doesn't match any cases") - @staticmethod - def check_lower(value): - if value == Network.BITCOIN: - return - if value == Network.REGTEST: - return - raise ValueError(value) + @staticmethod + def check_lower(value): + if value == Network.BITCOIN: + return + if value == Network.REGTEST: + return + raise ValueError(value) + + @staticmethod + def write(value, buf): + if value == Network.BITCOIN: + buf.write_i32(1) + if value == Network.REGTEST: + buf.write_i32(2) + + + + + + + +class NodeEvent: + """ + A real-time event from the node. + """ + + def __init__(self): + raise RuntimeError("NodeEvent cannot be instantiated directly") + + # Each enum variant is a nested class of the enum itself. + class INVOICE_PAID: + """ + An invoice was paid. + """ + + details: "InvoicePaidEvent" + + def __init__(self,details: "InvoicePaidEvent"): + self.details = details + + def __str__(self): + return "NodeEvent.INVOICE_PAID(details={})".format(self.details) + + def __eq__(self, other): + if not other.is_INVOICE_PAID(): + return False + if self.details != other.details: + return False + return True + + class UNKNOWN: + """ + An unknown event type was received. This can happen if the + server sends a new event type that this client doesn't know about. + """ + + + def __init__(self,): + pass + + def __str__(self): + return "NodeEvent.UNKNOWN()".format() + + def __eq__(self, other): + if not other.is_UNKNOWN(): + return False + return True + + + + # For each variant, we have `is_NAME` and `is_name` methods for easily checking + # whether an instance is that variant. + def is_INVOICE_PAID(self) -> bool: + return isinstance(self, NodeEvent.INVOICE_PAID) + def is_invoice_paid(self) -> bool: + return isinstance(self, NodeEvent.INVOICE_PAID) + def is_UNKNOWN(self) -> bool: + return isinstance(self, NodeEvent.UNKNOWN) + def is_unknown(self) -> bool: + return isinstance(self, NodeEvent.UNKNOWN) + + +# Now, a little trick - we make each nested variant class be a subclass of the main +# enum class, so that method calls and instance checks etc will work intuitively. +# We might be able to do this a little more neatly with a metaclass, but this'll do. +NodeEvent.INVOICE_PAID = type("NodeEvent.INVOICE_PAID", (NodeEvent.INVOICE_PAID, NodeEvent,), {}) # type: ignore +NodeEvent.UNKNOWN = type("NodeEvent.UNKNOWN", (NodeEvent.UNKNOWN, NodeEvent,), {}) # type: ignore + + + + +class _UniffiConverterTypeNodeEvent(_UniffiConverterRustBuffer): + @staticmethod + def read(buf): + variant = buf.read_i32() + if variant == 1: + return NodeEvent.INVOICE_PAID( + _UniffiConverterTypeInvoicePaidEvent.read(buf), + ) + if variant == 2: + return NodeEvent.UNKNOWN( + ) + raise InternalError("Raw enum value doesn't match any cases") + + @staticmethod + def check_lower(value): + if value.is_INVOICE_PAID(): + _UniffiConverterTypeInvoicePaidEvent.check_lower(value.details) + return + if value.is_UNKNOWN(): + return + raise ValueError(value) + + @staticmethod + def write(value, buf): + if value.is_INVOICE_PAID(): + buf.write_i32(1) + _UniffiConverterTypeInvoicePaidEvent.write(value.details, buf) + if value.is_UNKNOWN(): + buf.write_i32(2) + + + + + + + +class OutputStatus(enum.Enum): + UNCONFIRMED = 0 + + CONFIRMED = 1 + + SPENT = 2 + + IMMATURE = 3 + + + +class _UniffiConverterTypeOutputStatus(_UniffiConverterRustBuffer): + @staticmethod + def read(buf): + variant = buf.read_i32() + if variant == 1: + return OutputStatus.UNCONFIRMED + if variant == 2: + return OutputStatus.CONFIRMED + if variant == 3: + return OutputStatus.SPENT + if variant == 4: + return OutputStatus.IMMATURE + raise InternalError("Raw enum value doesn't match any cases") + + @staticmethod + def check_lower(value): + if value == OutputStatus.UNCONFIRMED: + return + if value == OutputStatus.CONFIRMED: + return + if value == OutputStatus.SPENT: + return + if value == OutputStatus.IMMATURE: + return + raise ValueError(value) + + @staticmethod + def write(value, buf): + if value == OutputStatus.UNCONFIRMED: + buf.write_i32(1) + if value == OutputStatus.CONFIRMED: + buf.write_i32(2) + if value == OutputStatus.SPENT: + buf.write_i32(3) + if value == OutputStatus.IMMATURE: + buf.write_i32(4) + + + + + + + +class PayStatus(enum.Enum): + COMPLETE = 0 + + PENDING = 1 + + FAILED = 2 + + + +class _UniffiConverterTypePayStatus(_UniffiConverterRustBuffer): + @staticmethod + def read(buf): + variant = buf.read_i32() + if variant == 1: + return PayStatus.COMPLETE + if variant == 2: + return PayStatus.PENDING + if variant == 3: + return PayStatus.FAILED + raise InternalError("Raw enum value doesn't match any cases") + + @staticmethod + def check_lower(value): + if value == PayStatus.COMPLETE: + return + if value == PayStatus.PENDING: + return + if value == PayStatus.FAILED: + return + raise ValueError(value) + + @staticmethod + def write(value, buf): + if value == PayStatus.COMPLETE: + buf.write_i32(1) + if value == PayStatus.PENDING: + buf.write_i32(2) + if value == PayStatus.FAILED: + buf.write_i32(3) + + + + + +class _UniffiConverterOptionalUInt32(_UniffiConverterRustBuffer): + @classmethod + def check_lower(cls, value): + if value is not None: + _UniffiConverterUInt32.check_lower(value) + + @classmethod + def write(cls, value, buf): + if value is None: + buf.write_u8(0) + return + + buf.write_u8(1) + _UniffiConverterUInt32.write(value, buf) + + @classmethod + def read(cls, buf): + flag = buf.read_u8() + if flag == 0: + return None + elif flag == 1: + return _UniffiConverterUInt32.read(buf) + else: + raise InternalError("Unexpected flag byte for optional type") + + + +class _UniffiConverterOptionalUInt64(_UniffiConverterRustBuffer): + @classmethod + def check_lower(cls, value): + if value is not None: + _UniffiConverterUInt64.check_lower(value) + + @classmethod + def write(cls, value, buf): + if value is None: + buf.write_u8(0) + return + + buf.write_u8(1) + _UniffiConverterUInt64.write(value, buf) + + @classmethod + def read(cls, buf): + flag = buf.read_u8() + if flag == 0: + return None + elif flag == 1: + return _UniffiConverterUInt64.read(buf) + else: + raise InternalError("Unexpected flag byte for optional type") + + + +class _UniffiConverterOptionalString(_UniffiConverterRustBuffer): + @classmethod + def check_lower(cls, value): + if value is not None: + _UniffiConverterString.check_lower(value) + + @classmethod + def write(cls, value, buf): + if value is None: + buf.write_u8(0) + return + + buf.write_u8(1) + _UniffiConverterString.write(value, buf) + + @classmethod + def read(cls, buf): + flag = buf.read_u8() + if flag == 0: + return None + elif flag == 1: + return _UniffiConverterString.read(buf) + else: + raise InternalError("Unexpected flag byte for optional type") + + + +class _UniffiConverterOptionalBytes(_UniffiConverterRustBuffer): + @classmethod + def check_lower(cls, value): + if value is not None: + _UniffiConverterBytes.check_lower(value) + + @classmethod + def write(cls, value, buf): + if value is None: + buf.write_u8(0) + return + + buf.write_u8(1) + _UniffiConverterBytes.write(value, buf) + + @classmethod + def read(cls, buf): + flag = buf.read_u8() + if flag == 0: + return None + elif flag == 1: + return _UniffiConverterBytes.read(buf) + else: + raise InternalError("Unexpected flag byte for optional type") + + + +class _UniffiConverterOptionalTypeNodeEvent(_UniffiConverterRustBuffer): + @classmethod + def check_lower(cls, value): + if value is not None: + _UniffiConverterTypeNodeEvent.check_lower(value) + + @classmethod + def write(cls, value, buf): + if value is None: + buf.write_u8(0) + return + + buf.write_u8(1) + _UniffiConverterTypeNodeEvent.write(value, buf) + + @classmethod + def read(cls, buf): + flag = buf.read_u8() + if flag == 0: + return None + elif flag == 1: + return _UniffiConverterTypeNodeEvent.read(buf) + else: + raise InternalError("Unexpected flag byte for optional type") + + + +class _UniffiConverterSequenceString(_UniffiConverterRustBuffer): + @classmethod + def check_lower(cls, value): + for item in value: + _UniffiConverterString.check_lower(item) + + @classmethod + def write(cls, value, buf): + items = len(value) + buf.write_i32(items) + for item in value: + _UniffiConverterString.write(item, buf) + + @classmethod + def read(cls, buf): + count = buf.read_i32() + if count < 0: + raise InternalError("Unexpected negative sequence length") + + return [ + _UniffiConverterString.read(buf) for i in range(count) + ] + + + +class _UniffiConverterSequenceTypeFundChannel(_UniffiConverterRustBuffer): + @classmethod + def check_lower(cls, value): + for item in value: + _UniffiConverterTypeFundChannel.check_lower(item) + + @classmethod + def write(cls, value, buf): + items = len(value) + buf.write_i32(items) + for item in value: + _UniffiConverterTypeFundChannel.write(item, buf) + + @classmethod + def read(cls, buf): + count = buf.read_i32() + if count < 0: + raise InternalError("Unexpected negative sequence length") + + return [ + _UniffiConverterTypeFundChannel.read(buf) for i in range(count) + ] - @staticmethod - def write(value, buf): - if value == Network.BITCOIN: - buf.write_i32(1) - if value == Network.REGTEST: - buf.write_i32(2) +class _UniffiConverterSequenceTypeFundOutput(_UniffiConverterRustBuffer): + @classmethod + def check_lower(cls, value): + for item in value: + _UniffiConverterTypeFundOutput.check_lower(item) + + @classmethod + def write(cls, value, buf): + items = len(value) + buf.write_i32(items) + for item in value: + _UniffiConverterTypeFundOutput.write(item, buf) + + @classmethod + def read(cls, buf): + count = buf.read_i32() + if count < 0: + raise InternalError("Unexpected negative sequence length") + + return [ + _UniffiConverterTypeFundOutput.read(buf) for i in range(count) + ] -class _UniffiConverterOptionalString(_UniffiConverterRustBuffer): +class _UniffiConverterSequenceTypePeer(_UniffiConverterRustBuffer): @classmethod def check_lower(cls, value): - if value is not None: - _UniffiConverterString.check_lower(value) + for item in value: + _UniffiConverterTypePeer.check_lower(item) @classmethod def write(cls, value, buf): - if value is None: - buf.write_u8(0) - return + items = len(value) + buf.write_i32(items) + for item in value: + _UniffiConverterTypePeer.write(item, buf) - buf.write_u8(1) - _UniffiConverterString.write(value, buf) + @classmethod + def read(cls, buf): + count = buf.read_i32() + if count < 0: + raise InternalError("Unexpected negative sequence length") + + return [ + _UniffiConverterTypePeer.read(buf) for i in range(count) + ] + + + +class _UniffiConverterSequenceTypePeerChannel(_UniffiConverterRustBuffer): + @classmethod + def check_lower(cls, value): + for item in value: + _UniffiConverterTypePeerChannel.check_lower(item) + + @classmethod + def write(cls, value, buf): + items = len(value) + buf.write_i32(items) + for item in value: + _UniffiConverterTypePeerChannel.write(item, buf) @classmethod def read(cls, buf): - flag = buf.read_u8() - if flag == 0: - return None - elif flag == 1: - return _UniffiConverterString.read(buf) - else: - raise InternalError("Unexpected flag byte for optional type") + count = buf.read_i32() + if count < 0: + raise InternalError("Unexpected negative sequence length") + + return [ + _UniffiConverterTypePeerChannel.read(buf) for i in range(count) + ] # objects. class CredentialsProtocol(typing.Protocol): @@ -1268,7 +2832,8 @@ class CredentialsProtocol(typing.Protocol): background. """ - pass + def save(self, ): + raise NotImplementedError # Credentials is a Rust-only trait - it's a wrapper around a Rust implementation. class Credentials(): """ @@ -1312,6 +2877,15 @@ def load(cls, raw: "bytes"): + def save(self, ) -> "bytes": + return _UniffiConverterBytes.lift( + _uniffi_rust_call_with_error(_UniffiConverterTypeError,_UniffiLib.uniffi_glsdk_fn_method_credentials_save,self._uniffi_clone_pointer(),) + ) + + + + + class _UniffiConverterTypeCredentials: @@ -1423,7 +2997,83 @@ class NodeProtocol(typing.Protocol): cloud. It is the main entrypoint to interact with the node. """ - pass + def get_info(self, ): + """ + Get information about the node. + + Returns basic information about the node including its ID, + alias, network, and channel counts. + """ + + raise NotImplementedError + def list_funds(self, ): + """ + List all funds available to the node. + + Returns information about on-chain outputs and channel funds + that are available or pending. + """ + + raise NotImplementedError + def list_peer_channels(self, ): + """ + List all channels with peers. + + Returns detailed information about all channels including their + state, capacity, and balances. + """ + + raise NotImplementedError + def list_peers(self, ): + """ + List all peers connected to this node. + + Returns information about all peers including their connection + status. + """ + + raise NotImplementedError + def onchain_receive(self, ): + raise NotImplementedError + def onchain_send(self, destination: "str",amount_or_all: "str"): + raise NotImplementedError + def receive(self, label: "str",description: "str",amount_msat: "typing.Optional[int]"): + """ + Receive an off-chain payment. + + This method generates a request for a payment, also called an + invoice, that encodes all the information, including amount + and destination, for a prospective sender to send a lightning + payment. The invoice includes negotiation of an LSPS2 / JIT + channel, meaning that if there is no channel sufficient to + receive the requested funds, the node will negotiate an + opening, and when/if executed the payment will cause a channel + to be created, and the incoming payment to be forwarded. + """ + + raise NotImplementedError + def send(self, invoice: "str",amount_msat: "typing.Optional[int]"): + raise NotImplementedError + def stop(self, ): + """ + Stop the node if it is currently running. + """ + + raise NotImplementedError + def stream_node_events(self, ): + """ + Stream real-time events from the node. + + Returns a `NodeEventStream` iterator. Call `next()` repeatedly + to receive events as they occur (e.g., invoice payments). + + The `next()` method blocks the calling thread until an event + is available, but does not block the underlying async runtime, + so other node methods can be called concurrently from other + threads. + """ + + raise NotImplementedError # Node is a Rust-only trait - it's a wrapper around a Rust implementation. class Node(): """ @@ -1457,6 +3107,173 @@ def _make_instance_(cls, pointer): return inst + def get_info(self, ) -> "GetInfoResponse": + """ + Get information about the node. + + Returns basic information about the node including its ID, + alias, network, and channel counts. + """ + + return _UniffiConverterTypeGetInfoResponse.lift( + _uniffi_rust_call_with_error(_UniffiConverterTypeError,_UniffiLib.uniffi_glsdk_fn_method_node_get_info,self._uniffi_clone_pointer(),) + ) + + + + + + def list_funds(self, ) -> "ListFundsResponse": + """ + List all funds available to the node. + + Returns information about on-chain outputs and channel funds + that are available or pending. + """ + + return _UniffiConverterTypeListFundsResponse.lift( + _uniffi_rust_call_with_error(_UniffiConverterTypeError,_UniffiLib.uniffi_glsdk_fn_method_node_list_funds,self._uniffi_clone_pointer(),) + ) + + + + + + def list_peer_channels(self, ) -> "ListPeerChannelsResponse": + """ + List all channels with peers. + + Returns detailed information about all channels including their + state, capacity, and balances. + """ + + return _UniffiConverterTypeListPeerChannelsResponse.lift( + _uniffi_rust_call_with_error(_UniffiConverterTypeError,_UniffiLib.uniffi_glsdk_fn_method_node_list_peer_channels,self._uniffi_clone_pointer(),) + ) + + + + + + def list_peers(self, ) -> "ListPeersResponse": + """ + List all peers connected to this node. + + Returns information about all peers including their connection + status. + """ + + return _UniffiConverterTypeListPeersResponse.lift( + _uniffi_rust_call_with_error(_UniffiConverterTypeError,_UniffiLib.uniffi_glsdk_fn_method_node_list_peers,self._uniffi_clone_pointer(),) + ) + + + + + + def onchain_receive(self, ) -> "OnchainReceiveResponse": + return _UniffiConverterTypeOnchainReceiveResponse.lift( + _uniffi_rust_call_with_error(_UniffiConverterTypeError,_UniffiLib.uniffi_glsdk_fn_method_node_onchain_receive,self._uniffi_clone_pointer(),) + ) + + + + + + def onchain_send(self, destination: "str",amount_or_all: "str") -> "OnchainSendResponse": + _UniffiConverterString.check_lower(destination) + + _UniffiConverterString.check_lower(amount_or_all) + + return _UniffiConverterTypeOnchainSendResponse.lift( + _uniffi_rust_call_with_error(_UniffiConverterTypeError,_UniffiLib.uniffi_glsdk_fn_method_node_onchain_send,self._uniffi_clone_pointer(), + _UniffiConverterString.lower(destination), + _UniffiConverterString.lower(amount_or_all)) + ) + + + + + + def receive(self, label: "str",description: "str",amount_msat: "typing.Optional[int]") -> "ReceiveResponse": + """ + Receive an off-chain payment. + + This method generates a request for a payment, also called an + invoice, that encodes all the information, including amount + and destination, for a prospective sender to send a lightning + payment. The invoice includes negotiation of an LSPS2 / JIT + channel, meaning that if there is no channel sufficient to + receive the requested funds, the node will negotiate an + opening, and when/if executed the payment will cause a channel + to be created, and the incoming payment to be forwarded. + """ + + _UniffiConverterString.check_lower(label) + + _UniffiConverterString.check_lower(description) + + _UniffiConverterOptionalUInt64.check_lower(amount_msat) + + return _UniffiConverterTypeReceiveResponse.lift( + _uniffi_rust_call_with_error(_UniffiConverterTypeError,_UniffiLib.uniffi_glsdk_fn_method_node_receive,self._uniffi_clone_pointer(), + _UniffiConverterString.lower(label), + _UniffiConverterString.lower(description), + _UniffiConverterOptionalUInt64.lower(amount_msat)) + ) + + + + + + def send(self, invoice: "str",amount_msat: "typing.Optional[int]") -> "SendResponse": + _UniffiConverterString.check_lower(invoice) + + _UniffiConverterOptionalUInt64.check_lower(amount_msat) + + return _UniffiConverterTypeSendResponse.lift( + _uniffi_rust_call_with_error(_UniffiConverterTypeError,_UniffiLib.uniffi_glsdk_fn_method_node_send,self._uniffi_clone_pointer(), + _UniffiConverterString.lower(invoice), + _UniffiConverterOptionalUInt64.lower(amount_msat)) + ) + + + + + + def stop(self, ) -> None: + """ + Stop the node if it is currently running. + """ + + _uniffi_rust_call_with_error(_UniffiConverterTypeError,_UniffiLib.uniffi_glsdk_fn_method_node_stop,self._uniffi_clone_pointer(),) + + + + + + + def stream_node_events(self, ) -> "NodeEventStream": + """ + Stream real-time events from the node. + + Returns a `NodeEventStream` iterator. Call `next()` repeatedly + to receive events as they occur (e.g., invoice payments). + + The `next()` method blocks the calling thread until an event + is available, but does not block the underlying async runtime, + so other node methods can be called concurrently from other + threads. + """ + + return _UniffiConverterTypeNodeEventStream.lift( + _uniffi_rust_call_with_error(_UniffiConverterTypeError,_UniffiLib.uniffi_glsdk_fn_method_node_stream_node_events,self._uniffi_clone_pointer(),) + ) + + + + + class _UniffiConverterTypeNode: @@ -1485,6 +3302,106 @@ def read(cls, buf: _UniffiRustBuffer): @classmethod def write(cls, value: NodeProtocol, buf: _UniffiRustBuffer): buf.write_u64(cls.lower(value)) +class NodeEventStreamProtocol(typing.Protocol): + """ + A stream of node events. Call `next()` to receive the next event. + + The stream is backed by a gRPC streaming connection to the node. + Each call to `next()` blocks the calling thread until an event is + available, but does not block the tokio runtime - other node + operations can proceed concurrently from other threads. + """ + + def next(self, ): + """ + Get the next event from the stream. + + Blocks the calling thread until an event is available or the + stream ends. Returns `None` when the stream is exhausted or + the connection is lost. + """ + + raise NotImplementedError +# NodeEventStream is a Rust-only trait - it's a wrapper around a Rust implementation. +class NodeEventStream(): + """ + A stream of node events. Call `next()` to receive the next event. + + The stream is backed by a gRPC streaming connection to the node. + Each call to `next()` blocks the calling thread until an event is + available, but does not block the tokio runtime - other node + operations can proceed concurrently from other threads. + """ + + _pointer: ctypes.c_void_p + + def __init__(self, *args, **kwargs): + raise ValueError("This class has no default constructor") + + def __del__(self): + # In case of partial initialization of instances. + pointer = getattr(self, "_pointer", None) + if pointer is not None: + _uniffi_rust_call(_UniffiLib.uniffi_glsdk_fn_free_nodeeventstream, pointer) + + def _uniffi_clone_pointer(self): + return _uniffi_rust_call(_UniffiLib.uniffi_glsdk_fn_clone_nodeeventstream, self._pointer) + + # Used by alternative constructors or any methods which return this type. + @classmethod + def _make_instance_(cls, pointer): + # Lightly yucky way to bypass the usual __init__ logic + # and just create a new instance with the required pointer. + inst = cls.__new__(cls) + inst._pointer = pointer + return inst + + + def next(self, ) -> "typing.Optional[NodeEvent]": + """ + Get the next event from the stream. + + Blocks the calling thread until an event is available or the + stream ends. Returns `None` when the stream is exhausted or + the connection is lost. + """ + + return _UniffiConverterOptionalTypeNodeEvent.lift( + _uniffi_rust_call_with_error(_UniffiConverterTypeError,_UniffiLib.uniffi_glsdk_fn_method_nodeeventstream_next,self._uniffi_clone_pointer(),) + ) + + + + + + +class _UniffiConverterTypeNodeEventStream: + + @staticmethod + def lift(value: int): + return NodeEventStream._make_instance_(value) + + @staticmethod + def check_lower(value: NodeEventStream): + if not isinstance(value, NodeEventStream): + raise TypeError("Expected NodeEventStream instance, {} found".format(type(value).__name__)) + + @staticmethod + def lower(value: NodeEventStreamProtocol): + if not isinstance(value, NodeEventStream): + raise TypeError("Expected NodeEventStream instance, {} found".format(type(value).__name__)) + return value._uniffi_clone_pointer() + + @classmethod + def read(cls, buf: _UniffiRustBuffer): + ptr = buf.read_u64() + if ptr == 0: + raise InternalError("Raw pointer value was null") + return cls.lift(ptr) + + @classmethod + def write(cls, value: NodeEventStreamProtocol, buf: _UniffiRustBuffer): + buf.write_u64(cls.lower(value)) class SchedulerProtocol(typing.Protocol): def recover(self, signer: "Signer"): raise NotImplementedError @@ -1676,11 +3593,29 @@ def write(cls, value: SignerProtocol, buf: _UniffiRustBuffer): __all__ = [ "InternalError", + "ChannelState", "Error", "Network", + "NodeEvent", + "OutputStatus", + "PayStatus", + "FundChannel", + "FundOutput", + "GetInfoResponse", + "InvoicePaidEvent", + "ListFundsResponse", + "ListPeerChannelsResponse", + "ListPeersResponse", + "OnchainReceiveResponse", + "OnchainSendResponse", + "Peer", + "PeerChannel", + "ReceiveResponse", + "SendResponse", "Credentials", "Handle", "Node", + "NodeEventStream", "Scheduler", "Signer", ] diff --git a/libs/gl-sdk/pyproject.toml b/libs/gl-sdk/pyproject.toml index bfc823dea..91bda92f6 100644 --- a/libs/gl-sdk/pyproject.toml +++ b/libs/gl-sdk/pyproject.toml @@ -25,6 +25,7 @@ dev = [ "gl-testing", "pdoc>=15.0.4", "pytest>=7.0", + "pytest-cov>=7.0.0", "pytest-watcher>=0.4.3", "rich>=10.0", ] @@ -37,3 +38,12 @@ testpaths = ["tests"] python_files = ["test_*.py"] python_classes = ["Test*"] python_functions = ["test_*"] +filterwarnings = [ + # Suppress X.509 CN length warning from gl-testing cert generation. + # The CN field includes the full node_id (66 hex chars), exceeding the + # 64-character limit specified in RFC 5280. This is safe to ignore because: + # - We control both client (gl-client) and server sides of the connection + # - gl-client's TLS implementation doesn't enforce strict X.509 CN length + # - This only affects test infrastructure, not production certificates + "ignore:Attribute's length must be >= 1 and <= 64:UserWarning", +] diff --git a/libs/gl-sdk/src/lib.rs b/libs/gl-sdk/src/lib.rs index 50d497bdb..8913103da 100644 --- a/libs/gl-sdk/src/lib.rs +++ b/libs/gl-sdk/src/lib.rs @@ -31,7 +31,12 @@ mod util; pub use crate::{ credentials::Credentials, - node::{Node, OnchainReceiveResponse, OnchainSendResponse, PayStatus, ReceiveResponse, SendResponse}, + node::{ + ChannelState, FundChannel, FundOutput, GetInfoResponse, InvoicePaidEvent, + ListFundsResponse, ListPeerChannelsResponse, ListPeersResponse, Node, NodeEvent, + NodeEventStream, OnchainReceiveResponse, OnchainSendResponse, OutputStatus, PayStatus, + Peer, PeerChannel, ReceiveResponse, SendResponse, + }, scheduler::Scheduler, signer::{Handle, Signer}, }; diff --git a/libs/gl-sdk/src/node.rs b/libs/gl-sdk/src/node.rs index ede5b034a..0fb679c48 100644 --- a/libs/gl-sdk/src/node.rs +++ b/libs/gl-sdk/src/node.rs @@ -1,8 +1,8 @@ use crate::{credentials::Credentials, util::exec, Error}; use gl_client::credentials::NodeIdProvider; use gl_client::node::{Client as GlClient, ClnClient, Node as ClientNode}; - -use gl_client::pb::cln as clnpb; +use gl_client::pb::{self as glpb, cln as clnpb}; +use std::sync::{Arc, Mutex}; use tokio::sync::OnceCell; /// The `Node` is an RPC stub representing the node running in the @@ -169,6 +169,89 @@ impl Node { .into_inner(); Ok(res.into()) } + + /// Get information about the node. + /// + /// Returns basic information about the node including its ID, + /// alias, network, and channel counts. + pub fn get_info(&self) -> Result { + let mut cln_client = exec(self.get_cln_client())?.clone(); + + let req = clnpb::GetinfoRequest {}; + + let res = exec(cln_client.getinfo(req)) + .map_err(|e| Error::Rpc(e.to_string()))? + .into_inner(); + Ok(res.into()) + } + + /// List all peers connected to this node. + /// + /// Returns information about all peers including their connection + /// status. + pub fn list_peers(&self) -> Result { + let mut cln_client = exec(self.get_cln_client())?.clone(); + + let req = clnpb::ListpeersRequest { + id: None, + level: None, + }; + + let res = exec(cln_client.list_peers(req)) + .map_err(|e| Error::Rpc(e.to_string()))? + .into_inner(); + Ok(res.into()) + } + + /// List all channels with peers. + /// + /// Returns detailed information about all channels including their + /// state, capacity, and balances. + pub fn list_peer_channels(&self) -> Result { + let mut cln_client = exec(self.get_cln_client())?.clone(); + + let req = clnpb::ListpeerchannelsRequest { id: None }; + + let res = exec(cln_client.list_peer_channels(req)) + .map_err(|e| Error::Rpc(e.to_string()))? + .into_inner(); + Ok(res.into()) + } + + /// List all funds available to the node. + /// + /// Returns information about on-chain outputs and channel funds + /// that are available or pending. + pub fn list_funds(&self) -> Result { + let mut cln_client = exec(self.get_cln_client())?.clone(); + + let req = clnpb::ListfundsRequest { spent: None }; + + let res = exec(cln_client.list_funds(req)) + .map_err(|e| Error::Rpc(e.to_string()))? + .into_inner(); + Ok(res.into()) + } + + /// Stream real-time events from the node. + /// + /// Returns a `NodeEventStream` iterator. Call `next()` repeatedly + /// to receive events as they occur (e.g., invoice payments). + /// + /// The `next()` method blocks the calling thread until an event + /// is available, but does not block the underlying async runtime, + /// so other node methods can be called concurrently from other + /// threads. + pub fn stream_node_events(&self) -> Result, Error> { + let mut gl_client = exec(self.get_gl_client())?.clone(); + let req = glpb::NodeEventsRequest {}; + let stream = exec(gl_client.stream_node_events(req)) + .map_err(|e| Error::Rpc(e.to_string()))? + .into_inner(); + Ok(Arc::new(NodeEventStream { + inner: Mutex::new(stream), + })) + } } // Not exported through uniffi @@ -276,3 +359,357 @@ impl From for PayStatus { } } } + +// ============================================================ +// GetInfo response types +// ============================================================ + +#[allow(unused)] +#[derive(Clone, uniffi::Record)] +pub struct GetInfoResponse { + pub id: Vec, + pub alias: Option, + pub color: Vec, + pub num_peers: u32, + pub num_pending_channels: u32, + pub num_active_channels: u32, + pub num_inactive_channels: u32, + pub version: String, + pub lightning_dir: String, + pub blockheight: u32, + pub network: String, + pub fees_collected_msat: u64, +} + +impl From for GetInfoResponse { + fn from(other: clnpb::GetinfoResponse) -> Self { + Self { + id: other.id, + alias: other.alias, + color: other.color, + num_peers: other.num_peers, + num_pending_channels: other.num_pending_channels, + num_active_channels: other.num_active_channels, + num_inactive_channels: other.num_inactive_channels, + version: other.version, + lightning_dir: other.lightning_dir, + blockheight: other.blockheight, + network: other.network, + fees_collected_msat: other.fees_collected_msat.map(|a| a.msat).unwrap_or(0), + } + } +} + + + +// ============================================================ +// ListPeers response types +// ============================================================ + +#[allow(unused)] +#[derive(Clone, uniffi::Record)] +pub struct ListPeersResponse { + pub peers: Vec, +} + +#[allow(unused)] +#[derive(Clone, uniffi::Record)] +pub struct Peer { + pub id: Vec, + pub connected: bool, + pub num_channels: Option, + pub netaddr: Vec, + pub remote_addr: Option, + pub features: Option>, +} + +impl From for ListPeersResponse { + fn from(other: clnpb::ListpeersResponse) -> Self { + Self { + peers: other.peers.into_iter().map(|p| p.into()).collect(), + } + } +} + +impl From for Peer { + fn from(other: clnpb::ListpeersPeers) -> Self { + Self { + id: other.id, + connected: other.connected, + num_channels: other.num_channels, + netaddr: other.netaddr, + remote_addr: other.remote_addr, + features: other.features, + } + } +} + + + +// ============================================================ +// ListPeerChannels response types +// ============================================================ + +#[allow(unused)] +#[derive(Clone, uniffi::Record)] +pub struct ListPeerChannelsResponse { + pub channels: Vec, +} + +#[allow(unused)] +#[derive(Clone, uniffi::Record)] +pub struct PeerChannel { + pub peer_id: Vec, + pub peer_connected: bool, + pub state: ChannelState, + pub short_channel_id: Option, + pub channel_id: Option>, + pub funding_txid: Option>, + pub funding_outnum: Option, + pub to_us_msat: Option, + pub total_msat: Option, + pub spendable_msat: Option, + pub receivable_msat: Option, +} + +#[derive(Clone, uniffi::Enum)] +pub enum ChannelState { + Openingd, + ChanneldAwaitingLockin, + ChanneldNormal, + ChanneldShuttingDown, + ClosingdSigexchange, + ClosingdComplete, + AwaitingUnilateral, + FundingSpendSeen, + Onchain, + DualopendOpenInit, + DualopendAwaitingLockin, + DualopendOpenCommitted, + DualopendOpenCommitReady, +} + +impl ChannelState { + fn from_i32(value: i32) -> Self { + match value { + 0 => ChannelState::Openingd, + 1 => ChannelState::ChanneldAwaitingLockin, + 2 => ChannelState::ChanneldNormal, + 3 => ChannelState::ChanneldShuttingDown, + 4 => ChannelState::ClosingdSigexchange, + 5 => ChannelState::ClosingdComplete, + 6 => ChannelState::AwaitingUnilateral, + 7 => ChannelState::FundingSpendSeen, + 8 => ChannelState::Onchain, + 9 => ChannelState::DualopendOpenInit, + 10 => ChannelState::DualopendAwaitingLockin, + 11 => ChannelState::DualopendOpenCommitted, + 12 => ChannelState::DualopendOpenCommitReady, + _ => ChannelState::Onchain, // Default fallback + } + } +} + +impl From for ListPeerChannelsResponse { + fn from(other: clnpb::ListpeerchannelsResponse) -> Self { + Self { + channels: other.channels.into_iter().map(|c| c.into()).collect(), + } + } +} + +impl From for PeerChannel { + fn from(other: clnpb::ListpeerchannelsChannels) -> Self { + let state = ChannelState::from_i32(other.state); + Self { + peer_id: other.peer_id, + peer_connected: other.peer_connected, + state, + short_channel_id: other.short_channel_id, + channel_id: other.channel_id, + funding_txid: other.funding_txid, + funding_outnum: other.funding_outnum, + to_us_msat: other.to_us_msat.map(|a| a.msat), + total_msat: other.total_msat.map(|a| a.msat), + spendable_msat: other.spendable_msat.map(|a| a.msat), + receivable_msat: other.receivable_msat.map(|a| a.msat), + } + } +} + + + +// ============================================================ +// ListFunds response types +// ============================================================ + +#[allow(unused)] +#[derive(Clone, uniffi::Record)] +pub struct ListFundsResponse { + pub outputs: Vec, + pub channels: Vec, +} + +#[allow(unused)] +#[derive(Clone, uniffi::Record)] +pub struct FundOutput { + pub txid: Vec, + pub output: u32, + pub amount_msat: u64, + pub status: OutputStatus, + pub address: Option, + pub blockheight: Option, +} + +#[derive(Clone, uniffi::Enum)] +pub enum OutputStatus { + Unconfirmed, + Confirmed, + Spent, + Immature, +} + +impl OutputStatus { + fn from_i32(value: i32) -> Self { + match value { + 0 => OutputStatus::Unconfirmed, + 1 => OutputStatus::Confirmed, + 2 => OutputStatus::Spent, + 3 => OutputStatus::Immature, + _ => OutputStatus::Unconfirmed, // Default fallback + } + } +} + +#[allow(unused)] +#[derive(Clone, uniffi::Record)] +pub struct FundChannel { + pub peer_id: Vec, + pub our_amount_msat: u64, + pub amount_msat: u64, + pub funding_txid: Vec, + pub funding_output: u32, + pub connected: bool, + pub state: ChannelState, + pub short_channel_id: Option, + pub channel_id: Option>, +} + +impl From for ListFundsResponse { + fn from(other: clnpb::ListfundsResponse) -> Self { + Self { + outputs: other.outputs.into_iter().map(|o| o.into()).collect(), + channels: other.channels.into_iter().map(|c| c.into()).collect(), + } + } +} + +impl From for FundOutput { + fn from(other: clnpb::ListfundsOutputs) -> Self { + let status = OutputStatus::from_i32(other.status); + Self { + txid: other.txid, + output: other.output, + amount_msat: other.amount_msat.map(|a| a.msat).unwrap_or(0), + status, + address: other.address, + blockheight: other.blockheight, + } + } +} + +impl From for FundChannel { + fn from(other: clnpb::ListfundsChannels) -> Self { + let state = ChannelState::from_i32(other.state); + Self { + peer_id: other.peer_id, + our_amount_msat: other.our_amount_msat.map(|a| a.msat).unwrap_or(0), + amount_msat: other.amount_msat.map(|a| a.msat).unwrap_or(0), + funding_txid: other.funding_txid, + funding_output: other.funding_output, + connected: other.connected, + state, + short_channel_id: other.short_channel_id, + channel_id: other.channel_id, + } + } +} + + + +// ============================================================ +// NodeEvent streaming types +// ============================================================ + +/// A stream of node events. Call `next()` to receive the next event. +/// +/// The stream is backed by a gRPC streaming connection to the node. +/// Each call to `next()` blocks the calling thread until an event is +/// available, but does not block the tokio runtime - other node +/// operations can proceed concurrently from other threads. +#[derive(uniffi::Object)] +pub struct NodeEventStream { + inner: Mutex>, +} + +#[uniffi::export] +impl NodeEventStream { + /// Get the next event from the stream. + /// + /// Blocks the calling thread until an event is available or the + /// stream ends. Returns `None` when the stream is exhausted or + /// the connection is lost. + pub fn next(&self) -> Result, Error> { + let mut stream = self.inner.lock().map_err(|e| Error::Other(e.to_string()))?; + match exec(stream.message()) { + Ok(Some(event)) => Ok(Some(event.into())), + Ok(None) => Ok(None), + Err(e) if e.code() == tonic::Code::Unknown => Ok(None), + Err(e) => Err(Error::Rpc(e.to_string())), + } + } +} + +/// A real-time event from the node. +#[derive(Clone, uniffi::Enum)] +pub enum NodeEvent { + /// An invoice was paid. + InvoicePaid { details: InvoicePaidEvent }, + /// An unknown event type was received. This can happen if the + /// server sends a new event type that this client doesn't know about. + Unknown, +} + +/// Details of a paid invoice. +#[derive(Clone, uniffi::Record)] +pub struct InvoicePaidEvent { + /// The payment hash of the paid invoice. + pub payment_hash: Vec, + /// The bolt11 invoice string. + pub bolt11: String, + /// The preimage that proves payment. + pub preimage: Vec, + /// The label assigned to the invoice. + pub label: String, + /// Amount received in millisatoshis. + pub amount_msat: u64, +} + +impl From for NodeEvent { + fn from(other: glpb::NodeEvent) -> Self { + match other.event { + Some(glpb::node_event::Event::InvoicePaid(paid)) => NodeEvent::InvoicePaid { + details: InvoicePaidEvent { + payment_hash: paid.payment_hash, + bolt11: paid.bolt11, + preimage: paid.preimage, + label: paid.label, + amount_msat: paid.amount_msat, + }, + }, + None => NodeEvent::Unknown, + } + } +} + + diff --git a/libs/gl-sdk/tests/test_node_events.py b/libs/gl-sdk/tests/test_node_events.py new file mode 100644 index 000000000..6e9b35533 --- /dev/null +++ b/libs/gl-sdk/tests/test_node_events.py @@ -0,0 +1,115 @@ +"""Tests for Node event streaming functionality. + +These tests verify that the UniFFI bindings correctly expose the NodeEventStream +and related types. +""" + +import pytest +import glsdk + + +class TestEventStreamTypes: + """Test that event streaming types are properly defined in the bindings.""" + + def test_node_event_stream_type_exists(self): + """Test that NodeEventStream type is available.""" + assert hasattr(glsdk, "NodeEventStream") + + def test_node_event_type_exists(self): + """Test that NodeEvent type is available.""" + assert hasattr(glsdk, "NodeEvent") + + def test_invoice_paid_event_type_exists(self): + """Test that InvoicePaidEvent type is available.""" + assert hasattr(glsdk, "InvoicePaidEvent") + + def test_node_event_has_invoice_paid_variant(self): + """Test that NodeEvent has INVOICE_PAID variant.""" + assert hasattr(glsdk.NodeEvent, "INVOICE_PAID") + + def test_node_event_has_unknown_variant(self): + """Test that NodeEvent has UNKNOWN variant.""" + assert hasattr(glsdk.NodeEvent, "UNKNOWN") + + def test_node_has_stream_node_events_method(self): + """Test that Node class has stream_node_events method.""" + assert hasattr(glsdk.Node, "stream_node_events") + + def test_node_event_stream_has_next_method(self): + """Test that NodeEventStream class has next method.""" + assert hasattr(glsdk.NodeEventStream, "next") + + +class TestInvoicePaidEventFields: + """Test that InvoicePaidEvent has expected fields.""" + + def test_invoice_paid_event_can_be_constructed(self): + """Test InvoicePaidEvent can be constructed with all fields.""" + event = glsdk.InvoicePaidEvent( + payment_hash=b"\x00" * 32, + bolt11="lnbcrt1...", + preimage=b"\x01" * 32, + label="test-invoice", + amount_msat=100000, + ) + assert event.payment_hash == b"\x00" * 32 + assert event.bolt11 == "lnbcrt1..." + assert event.preimage == b"\x01" * 32 + assert event.label == "test-invoice" + assert event.amount_msat == 100000 + + def test_invoice_paid_event_str(self): + """Test InvoicePaidEvent has a reasonable string representation.""" + event = glsdk.InvoicePaidEvent( + payment_hash=b"\x00" * 32, + bolt11="lnbcrt1...", + preimage=b"\x01" * 32, + label="test-invoice", + amount_msat=100000, + ) + str_repr = str(event) + assert "InvoicePaidEvent" in str_repr + assert "test-invoice" in str_repr + + +class TestNodeEventVariants: + """Test NodeEvent enum variants and their behavior.""" + + def test_invoice_paid_variant_construction(self): + """Test that INVOICE_PAID variant can be constructed.""" + details = glsdk.InvoicePaidEvent( + payment_hash=b"\x00" * 32, + bolt11="lnbcrt1...", + preimage=b"\x01" * 32, + label="test-invoice", + amount_msat=100000, + ) + event = glsdk.NodeEvent.INVOICE_PAID(details=details) + assert event.details == details + + def test_unknown_variant_construction(self): + """Test that UNKNOWN variant can be constructed.""" + event = glsdk.NodeEvent.UNKNOWN() + assert event is not None + + def test_invoice_paid_is_invoice_paid(self): + """Test is_invoice_paid() method on INVOICE_PAID variant.""" + details = glsdk.InvoicePaidEvent( + payment_hash=b"\x00" * 32, + bolt11="lnbcrt1...", + preimage=b"\x01" * 32, + label="test-invoice", + amount_msat=100000, + ) + event = glsdk.NodeEvent.INVOICE_PAID(details=details) + assert event.is_invoice_paid() + assert not event.is_unknown() + + def test_unknown_is_unknown(self): + """Test is_unknown() method on UNKNOWN variant.""" + event = glsdk.NodeEvent.UNKNOWN() + assert event.is_unknown() + assert not event.is_invoice_paid() + + + diff --git a/libs/gl-sdk/tests/test_node_methods.py b/libs/gl-sdk/tests/test_node_methods.py new file mode 100644 index 000000000..009edaadd --- /dev/null +++ b/libs/gl-sdk/tests/test_node_methods.py @@ -0,0 +1,188 @@ +"""Tests for Node methods like get_info, list_peers, list_peer_channels, list_funds. + +These tests verify that the UniFFI bindings correctly expose the new Node methods +and their response types. +""" + +import pytest +import glsdk + + +class TestResponseTypes: + """Test that response types are properly defined in the bindings.""" + + def test_get_info_response_type_exists(self): + """Test that GetInfoResponse type is available.""" + assert hasattr(glsdk, "GetInfoResponse") + + def test_list_peers_response_type_exists(self): + """Test that ListPeersResponse type is available.""" + assert hasattr(glsdk, "ListPeersResponse") + + def test_list_peer_channels_response_type_exists(self): + """Test that ListPeerChannelsResponse type is available.""" + assert hasattr(glsdk, "ListPeerChannelsResponse") + + def test_list_funds_response_type_exists(self): + """Test that ListFundsResponse type is available.""" + assert hasattr(glsdk, "ListFundsResponse") + + def test_peer_type_exists(self): + """Test that Peer type is available.""" + assert hasattr(glsdk, "Peer") + + def test_peer_channel_type_exists(self): + """Test that PeerChannel type is available.""" + assert hasattr(glsdk, "PeerChannel") + + def test_fund_output_type_exists(self): + """Test that FundOutput type is available.""" + assert hasattr(glsdk, "FundOutput") + + def test_fund_channel_type_exists(self): + """Test that FundChannel type is available.""" + assert hasattr(glsdk, "FundChannel") + + def test_channel_state_enum_exists(self): + """Test that ChannelState enum is available.""" + assert hasattr(glsdk, "ChannelState") + # Check some enum variants + assert hasattr(glsdk.ChannelState, "OPENINGD") + assert hasattr(glsdk.ChannelState, "CHANNELD_NORMAL") + assert hasattr(glsdk.ChannelState, "ONCHAIN") + + def test_output_status_enum_exists(self): + """Test that OutputStatus enum is available.""" + assert hasattr(glsdk, "OutputStatus") + # Check enum variants + assert hasattr(glsdk.OutputStatus, "UNCONFIRMED") + assert hasattr(glsdk.OutputStatus, "CONFIRMED") + assert hasattr(glsdk.OutputStatus, "SPENT") + + +class TestNodeMethods: + """Test that Node has the expected methods.""" + + def test_node_has_get_info_method(self): + """Test that Node class has get_info method.""" + assert hasattr(glsdk.Node, "get_info") + + def test_node_has_list_peers_method(self): + """Test that Node class has list_peers method.""" + assert hasattr(glsdk.Node, "list_peers") + + def test_node_has_list_peer_channels_method(self): + """Test that Node class has list_peer_channels method.""" + assert hasattr(glsdk.Node, "list_peer_channels") + + def test_node_has_list_funds_method(self): + """Test that Node class has list_funds method.""" + assert hasattr(glsdk.Node, "list_funds") + + +class TestResponseTypeFields: + """Test that response types have expected fields.""" + + def test_get_info_response_has_expected_fields(self): + """Test GetInfoResponse has expected field attributes.""" + # Create instance to check fields + response = glsdk.GetInfoResponse( + id=b"\x02" * 33, + alias="test-node", + color=b"\xff\x00\x00", + num_peers=0, + num_pending_channels=0, + num_active_channels=0, + num_inactive_channels=0, + version="v24.11", + lightning_dir="/tmp/lightning", + blockheight=100, + network="regtest", + fees_collected_msat=0, + ) + assert response.id == b"\x02" * 33 + assert response.alias == "test-node" + assert response.network == "regtest" + assert response.blockheight == 100 + + def test_list_peers_response_has_peers_field(self): + """Test ListPeersResponse has peers field.""" + response = glsdk.ListPeersResponse(peers=[]) + assert response.peers == [] + + def test_list_peer_channels_response_has_channels_field(self): + """Test ListPeerChannelsResponse has channels field.""" + response = glsdk.ListPeerChannelsResponse(channels=[]) + assert response.channels == [] + + def test_list_funds_response_has_expected_fields(self): + """Test ListFundsResponse has outputs and channels fields.""" + response = glsdk.ListFundsResponse(outputs=[], channels=[]) + assert response.outputs == [] + assert response.channels == [] + + def test_peer_record_has_expected_fields(self): + """Test Peer record has expected fields.""" + peer = glsdk.Peer( + id=b"\x03" * 33, + connected=True, + num_channels=1, + netaddr=["127.0.0.1:9735"], + remote_addr="192.168.1.1:9735", + features=b"\x00", + ) + assert peer.id == b"\x03" * 33 + assert peer.connected is True + assert peer.num_channels == 1 + assert "127.0.0.1:9735" in peer.netaddr + + def test_peer_channel_record_has_expected_fields(self): + """Test PeerChannel record has expected fields.""" + channel = glsdk.PeerChannel( + peer_id=b"\x03" * 33, + peer_connected=True, + state=glsdk.ChannelState.CHANNELD_NORMAL, + short_channel_id="123x1x0", + channel_id=b"\x00" * 32, + funding_txid=b"\xab" * 32, + funding_outnum=0, + to_us_msat=500000000, + total_msat=1000000000, + spendable_msat=400000000, + receivable_msat=400000000, + ) + assert channel.peer_id == b"\x03" * 33 + assert channel.peer_connected is True + assert channel.state == glsdk.ChannelState.CHANNELD_NORMAL + assert channel.total_msat == 1000000000 + + def test_fund_output_record_has_expected_fields(self): + """Test FundOutput record has expected fields.""" + output = glsdk.FundOutput( + txid=b"\xab" * 32, + output=0, + amount_msat=1000000000, + status=glsdk.OutputStatus.CONFIRMED, + address="bcrt1qtest", + blockheight=100, + ) + assert output.txid == b"\xab" * 32 + assert output.amount_msat == 1000000000 + assert output.status == glsdk.OutputStatus.CONFIRMED + + def test_fund_channel_record_has_expected_fields(self): + """Test FundChannel record has expected fields.""" + channel = glsdk.FundChannel( + peer_id=b"\x03" * 33, + our_amount_msat=500000000, + amount_msat=1000000000, + funding_txid=b"\xab" * 32, + funding_output=0, + connected=True, + state=glsdk.ChannelState.CHANNELD_NORMAL, + short_channel_id="123x1x0", + channel_id=b"\x00" * 32, + ) + assert channel.peer_id == b"\x03" * 33 + assert channel.our_amount_msat == 500000000 + assert channel.connected is True diff --git a/libs/gl-signerproxy/.resources/proto/glclient/greenlight.proto b/libs/gl-signerproxy/.resources/proto/glclient/greenlight.proto index a75224793..bc0651ca3 100644 --- a/libs/gl-signerproxy/.resources/proto/glclient/greenlight.proto +++ b/libs/gl-signerproxy/.resources/proto/glclient/greenlight.proto @@ -20,7 +20,6 @@ service Node { // // Currently includes off-chain payments received matching an // invoice or spontaneus paymens through keysend. - rpc StreamIncoming(StreamIncomingFilter) returns (stream IncomingPayment) {} // Stream the logs as they are produced by the node // @@ -109,8 +108,6 @@ message Amount { } // Options to stream_incoming to specify what to stream. -message StreamIncomingFilter { -} message TlvField { uint64 type = 1; diff --git a/libs/gl-testing/README.md b/libs/gl-testing/README.md index f4bf892db..d7ac4854d 100644 --- a/libs/gl-testing/README.md +++ b/libs/gl-testing/README.md @@ -145,6 +145,40 @@ TBD scheduled on the first `Scheduler.schedule` call and will run until the test completes. +## Known Warnings + +### X.509 CN Length Warning + +When running tests, you may see warnings like: + +``` +UserWarning: Attribute's length must be >= 1 and <= 64, but it was 81 +``` + +This warning comes from the `cryptography` library when generating +test certificates. The Common Name (CN) field in test certificates +includes the full node_id (a 66-character hex string), which exceeds +the 64-character limit specified in RFC 5280. + +**This warning is safe to ignore** because: + +- We control both the client (`gl-client`) and server sides of all + connections in the test environment +- `gl-client`'s TLS implementation does not enforce strict X.509 CN + length validation +- This only affects test infrastructure certificates, not production + certificates issued by Greenlight + +To suppress this warning in your test suite, add the following to your +`pyproject.toml`: + +```toml +[tool.pytest.ini_options] +filterwarnings = [ + "ignore:Attribute's length must be >= 1 and <= 64:UserWarning", +] +``` + ## Local Setup ### Dependencies diff --git a/libs/gl-testing/gltesting/certs.py b/libs/gl-testing/gltesting/certs.py index 7a7dd966c..ecd030183 100644 --- a/libs/gl-testing/gltesting/certs.py +++ b/libs/gl-testing/gltesting/certs.py @@ -232,7 +232,12 @@ def gencert(idpath): def gencert_from_csr(csr: bytes, recover=False, pairing=False): """Generate a leaf certificate to be used for actual communication from certificate signing request.""" - # Get idpath from CN value in certificate signing request + # Get idpath from CN value in certificate signing request. + # Note: This may trigger a UserWarning about CN length exceeding 64 chars + # (RFC 5280 limit) because the CN includes the full node_id (66 hex chars). + # This is safe to ignore since we control both client (gl-client) and server + # sides, and gl-client doesn't enforce strict X.509 CN length validation. + # See README.md "Known Warnings" section for details. mycsr = x509.load_pem_x509_csr(csr, default_backend) idpath = mycsr.subject.get_attributes_for_oid(NameOID.COMMON_NAME)[0].value diff --git a/libs/proto/glclient/greenlight.proto b/libs/proto/glclient/greenlight.proto index 63dd182c0..ba9528a6d 100644 --- a/libs/proto/glclient/greenlight.proto +++ b/libs/proto/glclient/greenlight.proto @@ -25,7 +25,6 @@ service Node { // // Currently includes off-chain payments received matching an // invoice or spontaneus paymens through keysend. - rpc StreamIncoming(StreamIncomingFilter) returns (stream IncomingPayment) {} // Stream the logs as they are produced by the node // @@ -43,6 +42,14 @@ service Node { // replayed if the stream is interrupted. rpc StreamCustommsg(StreamCustommsgRequest) returns (stream Custommsg) {} + // Stream node events in real-time. + // + // This is a unified event stream that delivers various node events + // as they occur, including invoice updates, peer changes, channel + // state changes, and balance updates. Events are not persisted and + // will not be replayed if the stream is interrupted. + rpc StreamNodeEvents(NodeEventsRequest) returns (stream NodeEvent) {} + //////////////////////////////// HSM Messages //////////////////////// // // The following messages are related to communicating HSM @@ -113,9 +120,6 @@ message Amount { } } -// Options to stream_incoming to specify what to stream. -message StreamIncomingFilter { -} message TlvField { uint64 type = 1; @@ -243,3 +247,38 @@ message LspInvoiceResponse { bytes payment_hash = 4; bytes payment_secret = 5; } + +// Request for streaming node events. Currently empty but defined as +// its own message type to allow adding filters in the future (e.g., +// filter by event type, invoice label, etc.) +message NodeEventsRequest { +} + +// A real-time event from the node. Uses oneof to discriminate between +// different event types. +message NodeEvent { + oneof event { + InvoicePaid invoice_paid = 1; + // Future event types: + // PeerConnected peer_connected = 2; + // PeerDisconnected peer_disconnected = 3; + // ChannelStateChanged channel_state_changed = 4; + // BalanceChanged balance_changed = 5; + } +} + +// Event emitted when an invoice is paid. +message InvoicePaid { + // The payment hash of the paid invoice. + bytes payment_hash = 1; + // The bolt11 invoice string. + string bolt11 = 2; + // The preimage that proves payment. + bytes preimage = 3; + // The label assigned to the invoice. + string label = 4; + // Amount received in millisatoshis. + uint64 amount_msat = 5; + // Extra TLV fields included in the payment. + repeated TlvField extratlvs = 6; +}