improvements around nip89 announcement

This commit is contained in:
Pablo Fernandez
2024-01-02 12:21:56 +00:00
parent 67c5252983
commit 77d8848a01
3 changed files with 105 additions and 1 deletions

View File

@@ -119,6 +119,18 @@ To enable this you'll need to configure a few things on your `nsecbunker.json` c
"your-domain-here": {
"nip05": "/your-nip05-nostr.json-file", // The location where NIP-05 entries to your domain are stored
"nip89": {
"profile": { // a kind:0-like profile
"name": "my cool nsecbunker instance", // The name of your nsecBunker instance
"about": "...",
},
"operator": "npub1l2vyh47mk2p0qlsku7hg0vn29faehy9hy34ygaclpn66ukqp3afqutajft", // (optional) npub of the operator of this nsecbunker
"relays": [ // list of relays where to publush the nip89 announcement
"https://relay.damus.io",
"https://pyramid.fiatjaf.com"
]
}
// Wallet configuration (optional)
"wallet": {
"lnbits": {
@@ -142,6 +154,18 @@ For this to work you'll need to run, in addition to `nsecbunkerd`, an lnbits ins
- [ ] TODO: Add NWC support
When booting up, the nsecbunkerd will publish a NIP-89 announcement (`kind:31990`), which is the way clients find out about your nsecbunker.
When a bunker provides a wallet and zapping service (`wallet` and `nostdressUrl` are configured), it will add tags:
```json
{
"tags": [
[ "f", "wallet" ],
[ "f", "zaps" ]
]
}
```
# Authors
* [pablof7z](nostr:npub1l2vyh47mk2p0qlsku7hg0vn29faehy9hy34ygaclpn66ukqp3afqutajft)

View File

@@ -1,8 +1,10 @@
import readline from 'readline';
import { getCurrentConfig, saveCurrentConfig } from '../config/index.js';
import { DomainConfig, IConfig, getCurrentConfig, saveCurrentConfig } from '../config/index.js';
import { decryptNsec } from '../config/keys.js';
import { fork } from 'child_process';
import { resolve } from 'path';
import NDK, { NDKAppHandlerEvent, NDKKind, NDKPrivateKeySigner, NDKUser, NostrEvent } from '@nostr-dev-kit/ndk';
import { debug } from 'console';
interface IOpts {
keys: string[];
@@ -11,6 +13,77 @@ interface IOpts {
adminNpubs: string[];
}
async function nip89announcement(configData: IConfig) {
const domains = configData.domains as Record<string, DomainConfig>;
for (const [ domain, config ] of Object.entries(domains)) {
const hasNip89 = !!config.nip89;
if (!hasNip89) continue;
const profile = config.nip89!.profile;
const relays = config.nip89!.relays;
if (!profile) {
console.log(`❌ No NIP-89 profile in configuration of ${domain}!`);
continue
}
if (!relays || relays.length === 0) {
console.log(`❌ No relays in NIP-89 configuration of ${domain}!`);
continue
}
const hasWallet = !!config.wallet;
const hasNostrdress = !!config.wallet?.lnbits?.nostdressUrl;
const ndk = new NDK({explicitRelayUrls: relays});
ndk.signer = new NDKPrivateKeySigner(configData.admin.key);
ndk.connect(5000).then(async () => {
const event = new NDKAppHandlerEvent(ndk, {
tags: [
[ "alt", "This is an nsecBunker announcement" ]
]
} as NostrEvent);
const operator = config.nip89!.operator;
if (operator) {
try {
const opUser = new NDKUser({npub: operator});
event.tags.push(["p", opUser.pubkey]);
} catch {}
}
try {
const user = await ndk.signer!.user();
const existingEvent = await ndk.fetchEvent({
authors: [user.pubkey],
kinds: [NDKKind.AppHandler],
"#k": [NDKKind.NostrConnect.toString()]
});
if (existingEvent) {
debug(`🔍 Found existing NIP-89 announcement for ${domain}:`, existingEvent.encode());
// update existing event
const dTag = existingEvent.tagValue("d");
event.tags.push(["d", dTag!])
} else {
debug(`🔍 No existing NIP-89 announcement for ${domain} found.`);
event.tags.push(["d", NDKKind.NostrConnect.toString()]);
}
event.content = JSON.stringify(profile);
event.tags.push(["k", NDKKind.NostrConnect.toString()])
if (hasWallet && hasNostrdress) {
// add wallet and zaps feature tags
event.tags.push(["f", "wallet"]);
event.tags.push(["f", "zaps"]);
}
await event.publish();
debug(`✅ Published NIP-89 announcement for ${domain}:`, event.encode());
} catch(e: any) { console.log(`❌ Failed to publish NIP-89 announcement for ${domain}!`, e.message); }
})
}
}
/**
* This command starts the nsecbunkerd process with an (optional)
* admin interface over websockets or redis.
@@ -24,6 +97,8 @@ export async function start(opts: IOpts) {
await saveCurrentConfig(opts.config, configData);
nip89announcement(configData);
if (opts.verbose) {
configData.verbose = opts.verbose;
}

View File

@@ -18,6 +18,11 @@ export interface IWalletConfig {
export interface DomainConfig {
nip05: string;
nip89?: {
profile: Record<string, string>;
operator?: string;
relays: string[];
},
wallet?: IWalletConfig;
defaultProfile?: Record<string, string>;
};