agent-pay 0.1.0

L402 + DID-signed invoices: agent-to-agent Lightning payments (Rust port of @p-vbordei/agent-pay)
Documentation
mod harness;

use std::collections::HashMap;
use std::sync::Arc;

use agent_pay::{
    did_key_from_public_key, generate_key_pair, FetchOptions, InnerHandler, LightningNode,
    MemoryLedger, MemoryNode, Paywall, PaywallOptions, PaywallResponse,
};
use harness::{make_fetch, SECRET};

#[tokio::test]
async fn e2e_roundtrip() {
    let kp = generate_key_pair();
    let did = did_key_from_public_key(&kp.public_key).unwrap();
    let ledger = MemoryLedger::new();
    let server: Arc<dyn LightningNode> = Arc::new(MemoryNode::new(ledger.clone(), "server"));
    let client: Arc<dyn LightningNode> = Arc::new(MemoryNode::new(ledger.clone(), "client"));

    let mut opts = PaywallOptions::new(
        did.clone(),
        kp.private_key,
        1234,
        "/report",
        server,
        SECRET.to_vec(),
    );
    opts.invoice_ttl_seconds = 300;
    let paywall = Arc::new(Paywall::new(opts));

    let handler: InnerHandler = Arc::new(|_p: String, _h: HashMap<String, String>| {
        Box::pin(async move {
            Ok(PaywallResponse {
                status: 200,
                json: Some(serde_json::json!({"ok": true, "body": "paid content"})),
                ..Default::default()
            })
        })
    });
    let fetch = make_fetch(paywall, handler);
    let mut fopts = FetchOptions::new(client, 5000, fetch);
    fopts.expected_did = Some(did);
    let res = agent_pay::fetch_with_l402("http://x/report", fopts)
        .await
        .unwrap();
    assert_eq!(res.status, 200);
    assert_eq!(
        res.json.unwrap(),
        serde_json::json!({"ok": true, "body": "paid content"})
    );
}