-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
ef72bd9
commit 08efd21
Showing
1 changed file
with
136 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,136 @@ | ||
/* | ||
Adapter library for working with Nostr. | ||
*/ | ||
|
||
// Global npm libraries | ||
import BchNostr from 'bch-nostr' | ||
import { RelayPool } from 'nostr' | ||
import RetryQueue from '@chris.troutner/retry-queue' | ||
import * as nip19 from 'nostr-tools/nip19' | ||
|
||
class NostrAdapter { | ||
constructor (localConfig = { nostrRelay: '', nostrTopic: '' }) { | ||
this.relayWs = localConfig.nostrRelay // | ||
this.topic = localConfig.nostrTopic | ||
|
||
if (!this.relayWs) { | ||
throw new Error( | ||
'"nostrRelay" must be passed when instantiate NostrAdapter' | ||
) | ||
} | ||
|
||
if (!this.topic) { | ||
throw new Error( | ||
'"nostrTopic" must be passed when instantiate NostrAdapter' | ||
) | ||
} | ||
|
||
// Encapsulate dependencies | ||
this.bchNostr = new BchNostr() | ||
this.RelayPool = RelayPool | ||
this.retryQueue = new RetryQueue({ | ||
concurrency: 1, | ||
attempts: 5, | ||
retryPeriod: 1000 | ||
}) | ||
|
||
// Bind the 'this' object | ||
this.start = this.start.bind(this) | ||
this.post = this.post.bind(this) | ||
this.read = this.read.bind(this) | ||
this.eventId2note = this.eventId2note.bind(this) | ||
} | ||
|
||
// Create nostr keys. | ||
// NOTE: WIF must be provided in this function instead the constructor function | ||
// we can provide it after app wallet creation. | ||
async start (WIF) { | ||
try { | ||
if (!WIF || typeof WIF !== 'string') { | ||
throw new Error('WIF must be a string!') | ||
} | ||
|
||
const { privKeyBuf, nostrPubKey } = | ||
this.bchNostr.keys.createNostrPubKeyFromWif({ wif: WIF }) | ||
|
||
this.privKeyBuf = privKeyBuf | ||
this.nostrPubKey = nostrPubKey | ||
|
||
console.log(`Nostr Pub Key : ${nostrPubKey}`) | ||
|
||
return true | ||
} catch (error) { | ||
console.log(`Error in nostr.js/start() ${error.message} `) | ||
throw error | ||
} | ||
} | ||
|
||
// Post a message over the instance-topic. | ||
async post (msg = '') { | ||
try { | ||
if (!msg || typeof msg !== 'string') { | ||
throw new Error('msg must be a string!') | ||
} | ||
|
||
const inObj = { | ||
kind: 867, | ||
privKeyBuf: this.privKeyBuf, | ||
nostrPubKey: this.nostrPubKey, | ||
relayWs: this.relayWs, | ||
msg, | ||
tags: [['t', this.topic]] | ||
} | ||
const eventId = await this.retryQueue.addToQueue(this.bchNostr.post.uploadToNostr, inObj) | ||
return eventId | ||
} catch (error) { | ||
console.log(`Error in nostr.js/post() ${error.message} `) | ||
throw error | ||
} | ||
} | ||
|
||
// Read a message over the instance-topic. | ||
async read (limit = 10) { | ||
try { | ||
if (typeof limit !== 'number' || limit < 1) { | ||
throw new Error('Limit must be greater than 0') | ||
} | ||
|
||
const relays = [this.relayWs] | ||
const pool = this.RelayPool(relays) | ||
|
||
const nostrData = new Promise((resolve, reject) => { | ||
const messages = [] | ||
|
||
pool.on('open', (relay) => { | ||
// relay.subscribe('REQ', { ids: [eventId] }) | ||
relay.subscribe('REQ', { limit, kinds: [867], '#t': [this.topic] }) | ||
}) | ||
|
||
pool.on('eose', (relay) => { | ||
relay.close() | ||
resolve(messages) | ||
}) | ||
|
||
pool.on('event', (relay, subId, ev) => { | ||
// console.log('ev: ', ev) | ||
messages.push({ content: ev.content, eventId: ev.id }) | ||
}) | ||
}) | ||
|
||
const messages = await nostrData | ||
|
||
return messages | ||
} catch (error) { | ||
console.log(`Error in nostr.js/read() ${error.message} `) | ||
throw error | ||
} | ||
} | ||
|
||
// Convert an Event ID into a `noteabc..` syntax that Astral expects. | ||
// This can be used to generate a link to Astral to display the post. | ||
eventId2note(eventId) { | ||
return nip19.noteEncode(eventId) | ||
} | ||
} | ||
|
||
export default NostrAdapter |