Skip to content

Commit e9d43ca

Browse files
committed
Add nip07 to README
1 parent a84e50f commit e9d43ca

1 file changed

Lines changed: 82 additions & 0 deletions

File tree

‎README.md‎

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,88 @@ bun run pr
4545

4646
CI runs the same checks (all except `format`) on every pull request.
4747

48+
## Retracting a bounty
49+
50+
There is no retract button yet. Until there is, publish a [NIP-09](https://github.com/nostr-protocol/nips/blob/master/09.md) deletion request by hand, from the browser console on any SatCode page, signed in with your NIP-07 extension.
51+
52+
Start by grabbing your pubkey and the relay list. Both later steps use them.
53+
54+
```js
55+
const pubkey = await window.nostr.getPublicKey();
56+
57+
// Keep in sync with DEFAULT_RELAYS in src/lib/ndk.ts
58+
const relays = [
59+
'wss://relay.damus.io',
60+
'wss://relay.snort.social',
61+
'wss://relay.nos.social',
62+
'wss://nos.lol',
63+
'wss://nostr.bitcoiner.social',
64+
'wss://relay.primal.net',
65+
'wss://nostr.land'
66+
];
67+
```
68+
69+
Now list the bounties you have published, and copy the address of the one you want gone. A bounty usually reaches only some of the relays, so ask all of them and collapse the answers by address. Cards link to `/bounties/<address>`, so you can also read one out of the URL bar instead.
70+
71+
```js
72+
const mine = new Map();
73+
74+
for (const url of relays) {
75+
const ws = new WebSocket(url);
76+
ws.onopen = () =>
77+
ws.send(
78+
JSON.stringify([
79+
'REQ',
80+
'mine',
81+
{ kinds: [30050], authors: [pubkey], limit: 50 }
82+
])
83+
);
84+
ws.onmessage = ({ data }) => {
85+
const [type, , event] = JSON.parse(data);
86+
if (type !== 'EVENT') return ws.close(); // EOSE, CLOSED, NOTICE
87+
const tag = (name) => event.tags.find((t) => t[0] === name)?.[1];
88+
mine.set(`30050:${event.pubkey}:${tag('d')}`, tag('title'));
89+
};
90+
setTimeout(() => ws.close(), 5000);
91+
}
92+
93+
// give it a few seconds, then
94+
console.table([...mine]);
95+
```
96+
97+
Then sign a kind 5 request naming that address, and send it to every relay:
98+
99+
```js
100+
const address = '30050:<pubkey>:<d>'; // from the table above
101+
102+
const request = await window.nostr.signEvent({
103+
kind: 5,
104+
pubkey,
105+
created_at: Math.floor(Date.now() / 1000),
106+
content: 'retracted',
107+
tags: [
108+
['a', address],
109+
['k', '30050']
110+
]
111+
});
112+
113+
for (const url of relays) {
114+
const ws = new WebSocket(url);
115+
ws.onopen = () => ws.send(JSON.stringify(['EVENT', request]));
116+
ws.onmessage = ({ data }) => {
117+
console.log(url, data);
118+
ws.close();
119+
};
120+
setTimeout(() => ws.close(), 5000);
121+
}
122+
```
123+
124+
Both tags matter. `a` names the bounty by address rather than by event id, so the request covers every revision of it. `k` is what the listing subscribes to, so a request without `["k", "30050"]` reaches the relays but stays invisible to SatCode.
125+
126+
Each relay answers `["OK", <id>, true, ""]` on success, or `false` with a reason. Relays that require [NIP-42](https://github.com/nostr-protocol/nips/blob/master/42.md) authentication will reject this, because the snippet does not authenticate and the app does, so a bounty published through SatCode may sit on relays this cannot reach.
127+
128+
Deletion is a request, not a command, and a relay may keep serving the event regardless. SatCode filters retracted bounties out client side, and only honours a request signed by the bounty's own author, so the card leaves the listing either way.
129+
48130
## License
49131
50132
This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or any later version.

0 commit comments

Comments
 (0)