lightning-pub/proto/service/structs.proto
padreug 77e5772afd
Some checks are pending
Docker Compose Actions Workflow / test (push) Waiting to run
feat(extensions): add extension loader infrastructure (#3)
## Summary

- Adds a modular extension system for Lightning.Pub enabling third-party plugins
- Provides isolated SQLite databases per extension for data safety
- Implements ExtensionContext API for accessing Lightning.Pub services (payments, Nostr, storage)
- Supports RPC method registration with automatic namespacing
- Includes HTTP route handling for protocols like LNURL
- Event routing for payment receipts and Nostr events
- Comprehensive documentation with architecture overview and working examples

## Key Components

- `src/extensions/types.ts` - Core extension interfaces
- `src/extensions/loader.ts` - Extension discovery, loading, and lifecycle management
- `src/extensions/context.ts` - Bridge between extensions and Lightning.Pub services
- `src/extensions/database.ts` - SQLite isolation with WAL mode
- `src/extensions/README.md` - Full documentation with examples

## ExtensionContext API

| Method | Description |
|--------|-------------|
| `getApplication()` | Get application info |
| `createInvoice()` | Create Lightning invoice |
| `payInvoice()` | Pay Lightning invoice |
| `getLnurlPayInfo()` | Get LNURL-pay info for a user (enables Lightning Address/zaps) |
| `sendEncryptedDM()` | Send Nostr DM (NIP-44) |
| `publishNostrEvent()` | Publish Nostr event |
| `registerMethod()` | Register RPC method |
| `onPaymentReceived()` | Subscribe to payment callbacks |
| `onNostrEvent()` | Subscribe to Nostr events |

## Test plan

- [x] Review extension loader code for correctness
- [x] Verify TypeScript compilation succeeds
- [x] Test extension discovery from `src/extensions/` directory
- [x] Test RPC method registration and routing
- [x] Test database isolation between extensions

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: boufni95 <boufni95@gmail.com>
Co-authored-by: Patrick Mulligan <patjmulligan@protonmail.com>
Reviewed-on: #3
2026-04-02 18:47:55 +00:00

1026 lines
No EOL
20 KiB
Protocol Buffer

syntax = "proto3";
package structs;
option go_package = "github.com/shocknet/lightning.pub";
message Empty {}
message LndSeed {
repeated string seed = 1;
}
message ZippedMetrics {
string path = 1;
}
message EncryptionExchangeRequest {
string publicKey = 1;
string deviceId = 2;
}
message AssetsAndLiabilitiesReq {
optional int64 limit_invoices = 1;
optional int64 limit_payments = 2;
optional int64 limit_providers = 4;
}
message BumpTx {
string txid = 1;
int64 output_index = 2;
int64 sat_per_vbyte = 3;
}
enum TrackedOperationType {
USER = 0;
ROOT = 1;
}
message TrackedOperation {
int64 ts = 1;
int64 amount = 2;
TrackedOperationType type = 3;
}
message AssetOperation {
int64 ts = 1;
int64 amount = 2;
optional TrackedOperation tracked = 3;
}
message TrackedLndProvider {
int64 confirmed_balance = 1;
int64 unconfirmed_balance = 2;
int64 channels_balance = 3;
repeated AssetOperation payments = 4;
repeated AssetOperation invoices = 5;
repeated AssetOperation incoming_tx = 6;
repeated AssetOperation outgoing_tx = 7;
}
message TrackedLiquidityProvider {
int64 balance = 1;
repeated AssetOperation payments = 2;
repeated AssetOperation invoices = 3;
}
message LndAssetProvider {
string pubkey = 1;
optional TrackedLndProvider tracked = 2;
}
message LiquidityAssetProvider {
string pubkey = 1;
optional TrackedLiquidityProvider tracked = 2;
}
message AssetsAndLiabilities {
int64 users_balance = 1;
repeated LndAssetProvider lnds = 2;
repeated LiquidityAssetProvider liquidity_providers = 3;
}
message UserHealthState {
string downtime_reason = 1;
}
message ErrorStat {
int64 from_unix = 1;
int64 total = 2;
int64 errors = 3;
}
message ErrorStats {
ErrorStat past24h = 1;
ErrorStat past6h = 2;
ErrorStat past1h = 3;
ErrorStat past10m = 4;
ErrorStat past1m = 5;
}
message MetricsFile {
}
message LatestUsageMetricReq {
optional int64 limit = 1;
}
enum SingleMetricType {
USAGE_METRIC = 0;
BUNDLE_METRIC = 1;
}
message SingleMetricReq {
string app_id = 1;
string metrics_name = 2;
int64 page = 3;
SingleMetricType metric_type = 4;
optional int64 request_id = 5;
}
message UsageMetric {
int64 processed_at_ms = 1;
int64 parsed_in_nano = 2;
int64 auth_in_nano = 3;
int64 validate_in_nano = 4;
int64 handle_in_nano = 5;
string rpc_name = 6;
bool batch = 7;
bool nostr = 8;
int64 batch_size = 9;
bool success = 10;
optional string app_id = 11;
}
message UsageMetricTlv {
repeated string base_64_tlvs = 1;
int64 current_chunk = 2;
repeated int64 available_chunks = 3;
}
message AppUsageMetrics {
map<string,UsageMetricTlv> app_metrics = 1;
}
message UsageMetrics {
map<string,AppUsageMetrics> apps = 1;
}
message LatestBundleMetricReq {
optional int64 limit = 1;
}
message BundleData {
repeated string base_64_data = 1;
int64 current_chunk = 2;
repeated int64 available_chunks = 3;
}
message BundleMetric {
map<string, BundleData> app_bundles = 1;
}
message BundleMetrics {
map<string, BundleMetric> apps = 1;
}
message AppsMetricsRequest {
optional int64 from_unix = 1;
optional int64 to_unix = 2;
optional bool include_operations = 3;
}
message UsersInfo {
int64 total = 1;
int64 no_balance = 2;
int64 negative_balance = 3;
int64 always_been_inactive = 4;
int64 balance_avg = 5;
int64 balance_median = 6;
}
message AppMetrics {
Application app = 1;
UsersInfo users = 2;
int64 received = 5;
int64 spent = 6;
int64 available = 7;
int64 fees = 8;
int64 invoices = 9;
int64 total_fees = 10;
repeated UserOperation operations = 100;
}
message AppsMetrics {
repeated AppMetrics apps = 1;
}
message LndMetricsRequest {
optional int64 from_unix = 1;
optional int64 to_unix = 2;
}
message RoutingEvent {
int64 incoming_channel_id = 1;
int64 incoming_htlc_id=2;
int64 outgoing_channel_id = 3;
int64 outgoing_htlc_id =4;
int64 timestamp_ns = 5;
string event_type = 6;
int64 incoming_amt_msat = 7;
int64 outgoing_amt_msat = 8;
string failure_string = 9;
bool settled = 10;
bool offchain = 11;
bool forward_fail_event = 12;
}
message ChannelPolicy {
int64 base_fee_msat= 1;
int64 fee_rate_ppm = 2;
int64 max_htlc_msat = 3;
int64 min_htlc_msat = 4;
int64 timelock_delta = 5;
}
message UpdateChannelPolicyRequest {
oneof update {
string channel_point = 1;
Empty all = 2;
}
ChannelPolicy policy = 3;
}
message OpenChannel {
string channel_id = 1;
int64 capacity = 2;
bool active = 3;
int64 lifetime =4;
int64 local_balance=5;
int64 remote_balance = 6;
string label = 7;
string channel_point = 8;
optional ChannelPolicy policy = 9;
int64 inactive_since_unix = 10;
}
message ClosedChannel {
string channel_id = 1;
int64 capacity = 2;
int64 closed_height =4;
int64 close_tx_timestamp = 5;
}
message GraphPoint {
int64 x = 1;
int64 y = 2;
}
enum OperationType {
CHAIN_OP = 0;
INVOICE_OP = 1;
}
message RootOperation {
OperationType op_type = 1;
string op_id = 2;
int64 amount = 3;
int64 created_at_unix = 4;
}
message LndForwardingEvent {
string chan_id_in = 1;
string chan_id_out = 2;
int64 amt_in = 3;
int64 amt_out = 4;
int64 fee = 5;
int64 at_unix = 6;
}
message LndForwardingMetrics {
int64 total_fees = 1;
repeated LndForwardingEvent events = 2;
}
message LndNodeMetrics {
repeated GraphPoint chain_balance = 1;
repeated GraphPoint channel_balance = 2;
repeated GraphPoint external_balance = 3;
int64 offline_channels = 4;
int64 online_channels = 5;
int64 pending_channels = 6;
int64 closing_channels = 7;
repeated OpenChannel open_channels = 8;
repeated ClosedChannel closed_channels = 9;
int64 forwarding_events = 11;
int64 forwarding_fees = 12;
repeated RootOperation root_ops = 13;
}
message LndMetrics {
repeated LndNodeMetrics nodes = 1;
}
message LndChannels {
repeated OpenChannel open_channels = 1;
}
message WebRtcMessage {
oneof message {
string offer = 1;
string candidate = 2;
}
}
message WebRtcAnswer {
optional string answer = 1;
}
message WebRtcCandidate {
string candidate = 1;
}
message OpenChannelRequest{
string node_pubkey = 1;
int64 local_funding_amount = 2;
int64 sat_per_v_byte = 3;
optional int64 push_sat = 5;
optional string close_address = 6;
}
message OpenChannelResponse{
string channel_id = 1;
}
message CloseChannelRequest{
bool force = 2;
int64 sat_per_v_byte = 3;
string funding_txid = 4;
int64 output_index = 5;
}
message CloseChannelResponse{
string closing_txid = 1;
}
message AddPeerRequest {
string pubkey = 1;
string host = 2;
int64 port = 3;
}
message LndGetInfoRequest {
int64 nodeId = 1;
}
message SetMockInvoiceAsPaidRequest {
string invoice = 1;
int64 amount =2;
}
message LndGetInfoResponse {
string alias = 1;
bool synced_to_chain = 2;
bool synced_to_graph = 3;
bool watchdog_barking = 4;
}
message BanUserRequest {
string user_id = 1;
}
message BannedAppUser {
string app_name = 1;
string app_id = 2;
string user_identifier = 3;
string nostr_pub = 4;
}
message BanUserResponse {
int64 balance_sats = 1;
repeated BannedAppUser banned_app_users = 2;
}
message AddAppRequest {
string name = 1;
bool allow_user_creation = 2;
}
message AuthAppRequest {
string name = 1;
optional bool allow_user_creation = 2;
}
message Application {
string name = 1;
string id = 2;
int64 balance = 3;
string npub = 4;
}
message AuthApp {
Application app = 1;
string auth_token = 2;
}
message AddAppUserRequest {
string identifier = 1;
bool fail_if_exists = 2;
int64 balance = 3;
}
message AppUser {
string identifier = 1;
UserInfo info = 2;
int64 max_withdrawable = 3;
}
message AddAppInvoiceRequest {
string payer_identifier = 1;
string http_callback_url = 2;
NewInvoiceRequest invoice_req = 3;
}
message AddAppUserInvoiceRequest {
string receiver_identifier = 1;
string payer_identifier = 2;
string http_callback_url = 3;
NewInvoiceRequest invoice_req = 4;
optional PayerData payer_data = 5;
optional string offer_string = 6;
optional bool rejectUnauthorized = 7;
optional string token = 8;
}
message GetAppUserRequest {
string user_identifier = 1;
}
message PayAppUserInvoiceRequest {
string user_identifier = 1;
string invoice = 2;
int64 amount = 3;
optional string debit_npub = 4;
optional CumulativeFees expected_fees = 5;
}
message SendAppUserToAppUserPaymentRequest {
string from_user_identifier = 1;
string to_user_identifier = 2;
int64 amount = 3;
}
message SendAppUserToAppPaymentRequest {
string from_user_identifier = 1;
int64 amount = 2;
}
message GetAppUserLNURLInfoRequest {
string user_identifier = 1;
string base_url_override = 2;
}
message SetMockAppUserBalanceRequest {
string user_identifier = 1;
int64 amount = 2;
}
message SetMockAppBalanceRequest {
int64 amount = 1;
}
enum AddressType {
WITNESS_PUBKEY_HASH = 0;
NESTED_PUBKEY_HASH = 1;
TAPROOT_PUBKEY = 2;
}
message NewAddressRequest {
AddressType addressType = 1;
}
message NewAddressResponse{
string address = 1;
}
message PayAddressRequest{
string address = 1;
int64 amountSats = 2;
int64 satsPerVByte = 3;
optional string swap_operation_id = 4;
}
message PayAddressResponse{
string txId = 1;
string operation_id = 2;
int64 service_fee = 3;
int64 network_fee = 4;
}
message PayerData {
map<string,string> data = 1;
}
message NewInvoiceRequest{
int64 amountSats = 1;
string memo = 2;
optional string zap = 3;
optional int64 expiry = 4;
optional bool blind = 5;
}
message NewInvoiceResponse{
string invoice = 1;
}
message DecodeInvoiceRequest{
string invoice = 1;
}
message DecodeInvoiceResponse{
int64 amount=1;
}
message PayInvoiceRequest{
string invoice = 1;
int64 amount = 2;
optional string debit_npub = 3;
optional CumulativeFees expected_fees = 4;
}
message PayInvoiceResponse{
string preimage = 1;
int64 amount_paid = 2;
string operation_id = 3;
int64 service_fee = 4;
int64 network_fee = 5;
int64 latest_balance = 6;
}
message GetPaymentStateRequest{
string invoice = 1;
}
message PaymentState{
int64 paid_at_unix = 1;
int64 amount = 2;
int64 service_fee = 3;
int64 network_fee = 4;
bool internal = 5;
string operation_id = 6;
}
message LnurlLinkResponse{
string lnurl = 1;
string k1 = 2;
}
message LnurlWithdrawInfoResponse {
string tag = 1;
string callback = 2;
string k1 = 3;
string defaultDescription = 4;
int64 minWithdrawable = 5; // millisatoshi - unsafe overflow possible, but very unlikely
int64 maxWithdrawable = 6; // millisatoshi - unsafe overflow possible, but very unlikely
string balanceCheck = 7;
string payLink = 8;
}
message LnurlPayInfoResponse {
string tag = 1;
string callback = 2;
int64 maxSendable = 3; // millisatoshi - unsafe overflow possible, but very unlikely
int64 minSendable = 4; // millisatoshi - unsafe overflow possible, but very unlikely
string metadata = 5;
bool allowsNostr = 6;
string nostrPubkey = 7;
}
message HandleLnurlPayResponse {
string pr = 1;
repeated Empty routes = 2;
}
message CallbackUrl {
string url = 1;
}
message UserInfo{
string userId = 1;
int64 balance = 2;
int64 max_withdrawable = 3;
string user_identifier = 4;
int64 service_fee_bps = 5;
int64 network_max_fee_bps = 6;
int64 network_max_fee_fixed = 7;
string noffer = 8;
string ndebit = 9;
string callback_url = 10;
string bridge_url = 11;
string nmanage = 12;
string topic_id = 13;
}
message OperationsCursor {
int64 ts = 1; // last timestamp
int64 id = 2; // last serial_id
}
message GetUserOperationsRequest{
OperationsCursor latestIncomingInvoice = 1;
OperationsCursor latestOutgoingInvoice = 2;
OperationsCursor latestIncomingTx = 3;
OperationsCursor latestOutgoingTx = 4;
OperationsCursor latestIncomingUserToUserPayment = 5;
OperationsCursor latestOutgoingUserToUserPayment = 6;
int64 max_size = 7;
}
enum UserOperationType {
INCOMING_TX =0;
OUTGOING_TX =1;
INCOMING_INVOICE =2;
OUTGOING_INVOICE=3;
OUTGOING_USER_TO_USER=4;
INCOMING_USER_TO_USER=5;
}
message UserOperation {
int64 paidAtUnix=1;
UserOperationType type = 2;
bool inbound =3;
int64 amount = 4;
string identifier = 5;
string operationId = 6;
int64 service_fee = 7;
int64 network_fee = 8;
bool confirmed = 9;
string tx_hash = 10;
bool internal = 11;
}
message UserOperations {
OperationsCursor fromIndex=1;
OperationsCursor toIndex=2;
repeated UserOperation operations=3;
}
message GetUserOperationsResponse{
UserOperations latestOutgoingInvoiceOperations=1;
UserOperations latestIncomingInvoiceOperations=2;
UserOperations latestOutgoingTxOperations=3;
UserOperations latestIncomingTxOperations=4;
UserOperations latestOutgoingUserToUserPayemnts=5;
UserOperations latestIncomingUserToUserPayemnts=6;
}
message AddProductRequest {
string name = 1;
int64 price_sats = 2;
}
message Product {
string id = 1;
string name = 2;
int64 price_sats = 3;
string noffer = 4;
}
message GetProductBuyLinkResponse {
string link = 1;
}
message LiveUserOperation {
UserOperation operation = 1;
int64 latest_balance = 2;
}
message MigrationUpdate {
optional ClosureMigration closure = 1;
optional RelaysMigration relays = 2;
}
message ClosureMigration {
int64 closes_at_unix = 1;
}
message RelaysMigration {
repeated string relays = 1;
}
message GetNPubLinking {
string user_identifier = 1;
}
message NPubLinking {
oneof state {
Empty unlinked = 1;
string linked_npub = 2;
string linking_token = 3;
}
}
message RequestNPubLinkingTokenRequest {
string user_identifier = 1;
}
message RequestNPubLinkingTokenResponse {
string token = 1;
}
message LinkNPubThroughTokenRequest {
string token = 1;
}
message HttpCreds {
string url = 1;
string token = 2;
}
message EnrollAdminTokenRequest {
string admin_token = 1;
}
message CreateOneTimeInviteLinkRequest {
optional int64 sats = 1;
}
message CreateOneTimeInviteLinkResponse {
string invitation_link = 1;
}
message UseInviteLinkRequest {
string invite_token = 1;
}
message GetInviteTokenStateRequest {
string invite_token = 1;
}
message GetInviteTokenStateResponse {
bool used = 1;
}
message DebitOperation {
string npub = 1;
}
message DebitAuthorizationRequest {
string authorize_npub = 1;
repeated DebitRule rules = 2;
optional string request_id = 3;
}
message ManageOperation {
string npub = 1;
}
message ManageAuthorizationRequest {
string authorize_npub = 1;
optional string request_id = 2;
bool ban = 3;
}
message ManageAuthorization {
string manage_id = 1;
bool authorized = 2;
string npub = 3;
}
message ManageAuthorizations {
repeated ManageAuthorization manages = 1;
}
message DebitAuthorization {
string debit_id = 1;
bool authorized = 2;
string npub = 3;
repeated DebitRule rules = 4;
}
message DebitAuthorizations {
repeated DebitAuthorization debits = 1;
}
message DebitExpirationRule {
int64 expires_at_unix = 1;
}
enum IntervalType {
DAY = 0;
WEEK = 1;
MONTH = 2;
}
message FrequencyRule {
int64 number_of_intervals = 1;
IntervalType interval = 2;
int64 amount = 3;
}
message DebitRule {
oneof rule {
DebitExpirationRule expiration_rule = 1;
FrequencyRule frequency_rule = 2;
}
}
message LiveDebitRequest {
string request_id = 1;
string npub = 2;
oneof debit {
string invoice = 3;
FrequencyRule frequency = 4;
Empty full_access = 5;
}
}
message LiveManageRequest {
string request_id = 1;
string npub = 2;
}
message DebitToAuthorize {
repeated DebitRule rules = 1;
optional string invoice = 2;
}
message DebitResponse {
string request_id = 1;
string npub = 2;
oneof response {
Empty denied = 3;
string invoice = 4;
DebitToAuthorize authorize = 5;
}
}
message OfferId {
string offer_id = 1;
}
message OfferConfig {
string offer_id = 1;
string label = 2;
int64 price_sats = 3;
string callback_url = 4;
repeated string payer_data = 5;
string noffer = 6;
bool default_offer = 7;
string token = 8;
bool rejectUnauthorized = 9;
int64 createdAtUnix = 10;
int64 updatedAtUnix = 11;
optional bool blind = 12;
}
message UserOffers {
repeated OfferConfig offers = 1;
}
message GetUserOfferInvoicesReq {
string offer_id = 1;
bool include_unpaid = 2;
}
message OfferInvoices {
repeated OfferInvoice invoices = 1;
}
message OfferInvoice {
string invoice = 1;
string offer_id = 2;
int64 paid_at_unix = 3;
int64 amount = 4;
map<string,string> data = 5;
}
message ProviderDisruption {
string provider_pubkey = 1;
string provider_type = 2;
int64 since_unix = 3;
}
message ProvidersDisruption {
repeated ProviderDisruption disruptions = 1;
}
message MessagingToken {
string device_id = 1;
string firebase_messaging_token = 2;
}
message InvoiceSwapRequest {
int64 amount_sats = 1;
}
message InvoiceSwapQuote {
string swap_operation_id = 1;
string invoice = 2;
int64 invoice_amount_sats = 3;
string address = 4;
int64 transaction_amount_sats = 5;
int64 chain_fee_sats = 6;
int64 service_fee_sats = 7;
string service_url = 8;
int64 swap_fee_sats = 9;
string tx_id = 10;
int64 paid_at_unix = 11;
int64 expires_at_block_height = 12;
}
message InvoiceSwapQuoteList {
repeated InvoiceSwapQuote quotes = 1;
}
message InvoiceSwapOperation {
InvoiceSwapQuote quote = 1;
optional UserOperation operation_payment = 2;
optional string failure_reason = 3;
optional int64 completed_at_unix = 6;
optional string refund_address = 7;
optional int64 refund_at_unix = 8;
optional string refund_tx_id = 9;
}
message InvoiceSwapsList {
repeated InvoiceSwapOperation swaps = 1;
int64 current_block_height = 3;
}
message RefundAdminInvoiceSwapRequest {
string swap_operation_id = 1;
int64 sat_per_v_byte = 2;
}
message PayAdminInvoiceSwapRequest {
string swap_operation_id = 1;
int64 sat_per_v_byte = 2;
optional bool no_claim = 3;
}
message AdminInvoiceSwapResponse {
string tx_id = 1;
}
message TransactionSwapRequest {
int64 transaction_amount_sats = 2;
}
message PayAdminTransactionSwapRequest {
string address = 1;
string swap_operation_id = 2;
}
message TransactionSwapQuote {
string swap_operation_id = 1;
int64 invoice_amount_sats = 2;
int64 transaction_amount_sats = 3;
int64 swap_fee_sats = 4;
int64 chain_fee_sats = 5;
int64 service_fee_sats = 7;
string service_url = 8;
int64 expires_at_block_height = 9;
int64 paid_at_unix = 10;
int64 completed_at_unix = 11;
}
message TransactionSwapQuoteList {
repeated TransactionSwapQuote quotes = 1;
}
message AdminTxSwapResponse {
string tx_id = 1;
int64 network_fee = 2;
}
message TxSwapOperation {
TransactionSwapQuote quote = 1;
optional UserOperation operation_payment = 2;
optional string failure_reason = 3;
optional string address_paid = 4;
optional string tx_id = 5;
}
message TxSwapsList {
repeated TxSwapOperation swaps = 1;
}
message CumulativeFees {
int64 serviceFeeFloor = 2;
int64 serviceFeeBps = 3;
}
message BeaconData {
string type = 1;
string name = 2;
optional string avatarUrl = 3;
optional string nextRelay = 4;
optional CumulativeFees fees = 5;
}
message PushNotificationEnvelope {
string topic_id = 1;
string app_npub_hex = 2;
string encrypted_payload = 3; // encrypted PushNotificationPayload
}
message PushNotificationPayload {
oneof data {
UserOperation received_operation = 1;
UserOperation sent_operation = 2;
}
}