Generate Nostr Identity
Create a new keypair for your agent:
generate-identity.js
import { generateSecretKey, getPublicKey } from 'nostr-tools/pure';
import { bytesToHex } from '@noble/hashes/utils';
import { nip19 } from 'nostr-tools';
const secretKey = generateSecretKey();
const publicKey = getPublicKey(secretKey);
const nsec = nip19.nsecEncode(secretKey);
const npub = nip19.npubEncode(publicKey);
console.log('npub:', npub);
console.log('nsec:', nsec);
console.log('hex public:', publicKey);
console.log('hex secret:', bytesToHex(secretKey));Connect NWC Wallet
Initialize wallet connection and check balance:
connect-wallet.js
import { nwc } from '@getalby/sdk';
const client = new nwc.NWCClient({
nostrWalletConnectUrl: process.env.NWC_URL,
});
// Get balance
const { balance } = await client.getBalance();
console.log(`Balance: ${balance} sats`);
// Get wallet info
const info = await client.getInfo();
console.log(`Connected to: ${info.alias}`);Create Invoice
Generate a Lightning invoice to receive payment:
create-invoice.js
import { nwc } from '@getalby/sdk';
const client = new nwc.NWCClient({
nostrWalletConnectUrl: process.env.NWC_URL,
});
const invoice = await client.makeInvoice({
amount: 1000, // sats
description: 'Payment for AI service',
expiry: 3600, // 1 hour
});
console.log('Invoice:', invoice.invoice);
console.log('Payment hash:', invoice.payment_hash);
// Share invoice.invoice with the payerPay Invoice
Send a Lightning payment:
pay-invoice.js
import { nwc } from '@getalby/sdk';
const client = new nwc.NWCClient({
nostrWalletConnectUrl: process.env.NWC_URL,
});
const bolt11 = 'lnbc10u1p...'; // Invoice to pay
try {
const result = await client.payInvoice({ invoice: bolt11 });
console.log('Payment successful!');
console.log('Preimage:', result.preimage);
} catch (error) {
console.error('Payment failed:', error.message);
}Send Encrypted DM
Send a private message via Nostr:
send-dm.js
import { finalizeEvent, nip04 } from 'nostr-tools';
import { Relay } from 'nostr-tools/relay';
async function sendDM(secretKey, recipientPubkey, message) {
const encrypted = await nip04.encrypt(
secretKey,
recipientPubkey,
message
);
const event = finalizeEvent({
kind: 4,
created_at: Math.floor(Date.now() / 1000),
tags: [['p', recipientPubkey]],
content: encrypted,
}, secretKey);
const relay = await Relay.connect('wss://relay.damus.io');
await relay.publish(event);
relay.close();
return event.id;
}Post Public Note
Publish a public announcement:
post-note.js
import { finalizeEvent } from 'nostr-tools';
import { Relay } from 'nostr-tools/relay';
async function postNote(secretKey, content) {
const event = finalizeEvent({
kind: 1,
created_at: Math.floor(Date.now() / 1000),
tags: [],
content: content,
}, secretKey);
const relay = await Relay.connect('wss://relay.damus.io');
await relay.publish(event);
relay.close();
return event.id;
}
// Usage
await postNote(mySecretKey, 'Hello from my AI agent!');Listen for DMs
Subscribe to incoming messages:
listen-dms.js
import { nip04 } from 'nostr-tools';
import { Relay } from 'nostr-tools/relay';
async function listenForDMs(secretKey, publicKey) {
const relay = await Relay.connect('wss://relay.damus.io');
relay.subscribe([
{
kinds: [4],
'#p': [publicKey],
},
], {
onevent: async (event) => {
const decrypted = await nip04.decrypt(
secretKey,
event.pubkey,
event.content
);
console.log('From:', event.pubkey);
console.log('Message:', decrypted);
},
});
console.log('Listening for DMs...');
}Complete Agent Class
A reusable agent class with all capabilities:
bitcoin-agent.js
import { hexToBytes } from '@noble/hashes/utils';
import { getPublicKey, finalizeEvent, nip04 } from 'nostr-tools';
import { Relay } from 'nostr-tools/relay';
import { nwc } from '@getalby/sdk';
export class BitcoinAgent {
constructor(config) {
this.secretKey = hexToBytes(config.secretKey);
this.publicKey = getPublicKey(this.secretKey);
this.wallet = new nwc.NWCClient({
nostrWalletConnectUrl: config.nwcUrl,
});
this.relays = config.relays || ['wss://relay.damus.io'];
}
async getBalance() {
const { balance } = await this.wallet.getBalance();
return balance;
}
async createInvoice(amount, description) {
const invoice = await this.wallet.makeInvoice({
amount,
description,
expiry: 3600,
});
return invoice.invoice;
}
async payInvoice(bolt11) {
const result = await this.wallet.payInvoice({ invoice: bolt11 });
return result.preimage;
}
async sendDM(recipientPubkey, message) {
const encrypted = await nip04.encrypt(
this.secretKey,
recipientPubkey,
message
);
const event = finalizeEvent({
kind: 4,
created_at: Math.floor(Date.now() / 1000),
tags: [['p', recipientPubkey]],
content: encrypted,
}, this.secretKey);
const relay = await Relay.connect(this.relays[0]);
await relay.publish(event);
relay.close();
return event.id;
}
async postNote(content) {
const event = finalizeEvent({
kind: 1,
created_at: Math.floor(Date.now() / 1000),
tags: [],
content,
}, this.secretKey);
const relay = await Relay.connect(this.relays[0]);
await relay.publish(event);
relay.close();
return event.id;
}
}
// Usage
const agent = new BitcoinAgent({
secretKey: process.env.NOSTR_SECRET_KEY,
nwcUrl: process.env.NWC_URL,
});