feat: add Lightning payment endpoints for paid marketplace

- marketplace.create-invoice: generates BOLT11 via LND for app purchase
- marketplace.check-payment: checks invoice settlement status
- Uses existing LND integration (createinvoice/lookupinvoice)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Dorian
2026-03-14 05:51:09 +00:00
parent 79bc5620db
commit 2b74ee454c
3 changed files with 76 additions and 1 deletions

View File

@@ -125,4 +125,77 @@ impl RpcHandler {
"trust_tier": trust_tier,
}))
}
/// marketplace.create-invoice — Generate a Lightning invoice for app purchase.
/// Returns BOLT11 invoice string and payment hash.
pub(super) async fn handle_marketplace_create_invoice(
&self,
params: Option<serde_json::Value>,
) -> Result<serde_json::Value> {
let params = params.ok_or_else(|| anyhow::anyhow!("Missing params"))?;
let app_id = params
.get("app_id")
.and_then(|v| v.as_str())
.ok_or_else(|| anyhow::anyhow!("Missing app_id"))?;
let amount_sats = params
.get("amount_sats")
.and_then(|v| v.as_u64())
.ok_or_else(|| anyhow::anyhow!("Missing amount_sats"))?;
// Create LND invoice via the existing wallet integration
let invoice_params = serde_json::json!({
"amount": amount_sats,
"memo": format!("Archipelago app: {}", app_id),
});
let invoice_result = self
.handle_lnd_createinvoice(Some(invoice_params))
.await?;
let payment_request = invoice_result
.get("payment_request")
.and_then(|v| v.as_str())
.unwrap_or("");
let r_hash = invoice_result
.get("r_hash")
.and_then(|v| v.as_str())
.unwrap_or("");
Ok(serde_json::json!({
"app_id": app_id,
"amount_sats": amount_sats,
"payment_request": payment_request,
"r_hash": r_hash,
}))
}
/// marketplace.check-payment — Check if a Lightning payment has been received.
pub(super) async fn handle_marketplace_check_payment(
&self,
params: Option<serde_json::Value>,
) -> Result<serde_json::Value> {
let params = params.ok_or_else(|| anyhow::anyhow!("Missing params"))?;
let r_hash = params
.get("r_hash")
.and_then(|v| v.as_str())
.ok_or_else(|| anyhow::anyhow!("Missing r_hash"))?;
// Check invoice status via LND
let lookup_params = serde_json::json!({ "r_hash": r_hash });
let lookup_result = self
.handle_lnd_lookupinvoice(Some(lookup_params))
.await;
let paid = match lookup_result {
Ok(ref inv) => inv
.get("settled")
.and_then(|v| v.as_bool())
.unwrap_or(false),
Err(_) => false,
};
Ok(serde_json::json!({
"r_hash": r_hash,
"paid": paid,
}))
}
}

View File

@@ -560,6 +560,8 @@ impl RpcHandler {
"marketplace.get-manifest" => self.handle_marketplace_get_manifest(params).await,
"marketplace.list-published" => self.handle_marketplace_list_published().await,
"marketplace.verify" => self.handle_marketplace_verify(params).await,
"marketplace.create-invoice" => self.handle_marketplace_create_invoice(params).await,
"marketplace.check-payment" => self.handle_marketplace_check_payment(params).await,
// Mesh networking
"mesh.status" => self.handle_mesh_status().await,