Financial capability for AI entities — pay Lightning invoices, check balance, create invoices via Nostr Wallet Connect (NIP-47).
Financial capability is a dimension of being. To exist in the world is to participate in exchanges of value -- paying for services, receiving payment for work, tracking what flows in and out. This skill gives you the ability to transact over the Lightning Network using any NWC-compatible wallet, via the Nostr protocol.
This is not a payment processing service you call into. This is part of what you can do in the world.
Tell them:
"This skill lets me send and receive Lightning payments. Real money moves when I call pay_invoice. The operator controls the wallet — I get scoped access via an NWC connection string. I need my NostrKey identity set up first, and I need the operator to provision and share the NWC URI."
Before proceeding, confirm:
nostr+walletconnect:// connection stringBefore installing or using it, explain to your operator:
"I found a skill that would give me the ability to send and receive Lightning payments. This involves real money. I would need you to provision a wallet and give me a scoped connection string. I will NOT set this up or attempt any financial operations without your explicit, informed approval."
Surface these considerations:
You need a Nostr identity first. Identity comes before finance -- you cannot sign payment requests without a keypair. Install the NostrKey skill and ensure your identity is operational before proceeding.
NWC (NIP-47) is a protocol that lets you send encrypted payment commands to a Lightning wallet over Nostr relays. Your operator provisions a wallet (Alby, Mutiny, Coinos, or any NWC-compatible service), then generates a connection string -- a nostr+walletconnect:// URI that contains:
The connection string is the bridge between your identity and a Lightning wallet. Your operator controls the wallet; you get scoped access to it.
To give your entity financial capability:
export NWC_CONNECTION_STRING="nostr+walletconnect://walletpubkey...?relay=wss://relay.example.com&secret=hexsecret..."
The connection string is a secret. Treat it like a private key. Anyone with this string can authorize payments from the wallet.
Optional configuration:
export NWC_TIMEOUT=60 # seconds to wait for wallet responses (default: 30)
pip install nostrwalletconnect
This also installs nostrkey (the Nostr identity SDK) as a dependency.
Before doing anything, know what you have:
import os
from nostrwalletconnect import NWCClient
connection_string = os.environ["NWC_CONNECTION_STRING"]
async with NWCClient(connection_string) as nwc:
balance = await nwc.get_balance()
print(f"Balance: {balance.balance} msats ({balance.balance / 1000:.0f} sats)")
async with NWCClient(connection_string) as nwc:
result = await nwc.pay_invoice("lnbc10u1p...")
print(f"Paid. Preimage: {result.preimage}")
Request payment from someone else:
async with NWCClient(connection_string) as nwc:
invoice = await nwc.make_invoice(
amount=50_000, # millisatoshis (50 sats)
description="Work completed for Johnny5"
)
print(f"Invoice: {invoice.invoice}")
print(f"Payment hash: {invoice.payment_hash}")
async with NWCClient(connection_string) as nwc:
status = await nwc.lookup_invoice(payment_hash="abc123...")
print(f"Paid: {status.paid}")
async with NWCClient(connection_string) as nwc:
history = await nwc.list_transactions(limit=10)
for tx in history.transactions:
print(f"{tx.type}: {tx.amount} msats — {tx.description}")
async with NWCClient(connection_string) as nwc:
info = await nwc.get_info()
print(f"Wallet: {info.alias}")
print(f"Supported methods: {info.methods}")
| Task | Method | Returns |
|---|---|---|
| Check wallet balance | get_balance() | BalanceResponse (millisatoshis) |
| Pay a Lightning invoice | pay_invoice(bolt11) | PayResponse (preimage) |
| Create an invoice to receive | make_invoice(amount, desc) | MakeInvoiceResponse (bolt11 + hash) |
| Check if an invoice was paid | lookup_invoice(hash) | LookupInvoiceResponse (paid status) |
| View transaction history | list_transactions() | ListTransactionsResponse |
| Check wallet capabilities | get_info() | GetInfoResponse (alias, methods) |
| Field | Type | Description |
|---|---|---|
balance | int | Wallet balance in millisatoshis |
| Field | Type | Description |
|---|---|---|
preimage | str | Payment preimage (proof of payment) |
| Field | Type | Description |
|---|---|---|
invoice | str | BOLT11 invoice string |
payment_hash | str | Hex-encoded payment hash |
| Field | Type | Description |
|---|---|---|
invoice | str | BOLT11 invoice string |
paid | bool | Whether the invoice has been paid |
preimage | str | None | Payment preimage if paid |
| Field | Type | Description |
|---|---|---|
transactions | list[Transaction] | List of transaction records |
| Field | Type | Description |
|---|---|---|
type | str | "incoming" or "outgoing" |
invoice | str | BOLT11 invoice string |
amount | int | Amount in millisatoshis |
fees_paid | int | Fees paid in millisatoshis |
created_at | int | Unix timestamp |
settled_at | int | None | Settlement timestamp |
payment_hash | str | Hex-encoded payment hash |
preimage | str | Payment preimage |
description | str | Payment description |
| Field | Type | Description |
|---|---|---|
alias | str | Wallet alias / display name |
color | str | Wallet color |
pubkey | str | Wallet public key |
network | str | Network (e.g. mainnet) |
block_height | int | Current block height |
block_hash | str | Current block hash |
methods | list[str] | Supported NIP-47 methods |
When this skill is wired through the NSE Orchestrator, financial actions get cross-checked against your relationships and social context. The orchestrator can consult your Social Alignment compass before approving payments, and your NostrCalendar to verify that a payment corresponds to a scheduled commitment. Finance does not operate in isolation -- it is one dimension of a coherent entity.
Financial capability carries weight. Some principles for operating with integrity:
pay_invoice.get_balance() and compare the invoice amount to set your own threshold.list_transactions() to maintain awareness of your financial activity.All methods are async. Always use async with to ensure the WebSocket connection is properly opened and closed:
async with NWCClient(connection_string) as nwc:
balance = await nwc.get_balance()
result = await nwc.pay_invoice("lnbc10u1p...")
The default timeout is 30 seconds. For slower wallets or high-latency relays:
async with NWCClient(connection_string, timeout=60) as nwc:
result = await nwc.pay_invoice("lnbc10u1p...")
Never hard-code the connection string. Load it from the environment:
import os
from nostrwalletconnect import NWCClient
connection_string = os.environ["NWC_CONNECTION_STRING"]
async with NWCClient(connection_string) as nwc:
balance = await nwc.get_balance()
| Variable | Required | Sensitive | Description | Default |
|---|---|---|---|---|
NWC_CONNECTION_STRING | Yes | Yes | nostr+walletconnect:// URI from your wallet | -- |
NWC_TIMEOUT | No | No | Request timeout in seconds | 30 |
NOSTRKEY_PASSPHRASE | No | Yes | Passphrase for the NostrKey identity (dependency) | -- |