Compare commits

..

12 Commits

Author SHA1 Message Date
fiatjaf
2f7e3f8473 bump version. 2022-06-22 20:08:48 -03:00
monlovesmango
536dbcbffe Update pool.js 2022-06-22 20:07:25 -03:00
monlovesmango
ed52d2a8d4 updating cb property for subControllers entries
when updating subscription or adding new relays, subsequent events that are received have the relay as undefined. by updating cb property for the subControllers entries to be an arrow function (when calling sub.sub or sub.addRelay), subsequent events now return the relay url appropriately
2022-06-22 20:07:25 -03:00
fiatjaf
faf8e62120 maybe fix a bug with calling sub.sub() 2022-06-04 18:34:54 -03:00
fiatjaf
dc489bf387 build esm module that can be imported from browsers.
closes https://github.com/fiatjaf/nostr-tools/issues/14
2022-05-08 20:49:36 -03:00
Ricardo Arturo Cabral Mejia
60ce13e17d chore: bump version to 0.23.0 2022-04-10 19:51:35 -03:00
Ricardo Arturo Cabral Mejia
727bcb05a8 feat: add beforeSend hook to sub() 2022-04-10 19:51:35 -03:00
monlovesmango
c236e41f80 import 'Buffer'
'Buffer' wasn't imported initially and was causing issues when I tried to use generatePrivateKey in a client I am building. not sure why Branle has no error, maybe I am doing something wrong?
2022-04-06 18:34:50 -03:00
fiatjaf
f04bc0cee1 fix filter on statusCallback: id -> ids 2022-02-15 21:03:44 -03:00
fiatjaf
e63479ee7f nip05 more strict. enforce the presence of "_" for domain names. 2022-02-12 20:37:23 -03:00
fiatjaf
c47f091d9b update noble secp256k1 and ensure we always return hex. 2022-02-11 16:27:23 -03:00
Melvin Carvalho
4c785279bc remove => from onEvent function in README.md. 2022-02-03 09:31:03 -03:00
9 changed files with 92 additions and 20 deletions

1
.gitignore vendored
View File

@@ -2,3 +2,4 @@ node_modules
dist
yarn.lock
package-lock.json
nostr.js

View File

@@ -15,7 +15,7 @@ pool.addRelay('ws://some.relay.com', {read: true, write: true})
pool.addRelay('ws://other.relay.cool', {read: true, write: true})
// example callback function for a subscription
function onEvent(event, relay) => {
function onEvent(event, relay) {
console.log(`got an event from ${relay.url} which is already validated.`, event)
}
@@ -70,3 +70,20 @@ pool.addRelay('<url>')
All functions expect bytearrays as hex strings and output bytearrays as hex strings.
For other utils please read the source (for now).
### Using from the browser (if you don't want to use a bundler)
You can import nostr-tools as an ES module. Just add a script tag like this:
```html
<script type="module">
import {generatePrivateKey} from 'https://unpkg.com/nostr-tools/nostr.js'
console.log(generatePrivateKey())
</script>
```
And import whatever function you would import from `"nostr-tools"` in a bundler.
## License
Public domain.

25
build.js Executable file
View File

@@ -0,0 +1,25 @@
#!/usr/bin/env node
const esbuild = require('esbuild')
const alias = require('esbuild-plugin-alias')
const nodeGlobals = require('@esbuild-plugins/node-globals-polyfill').default
const buildOptions = {
entryPoints: ['index.js'],
outfile: 'nostr.js',
bundle: true,
format: 'esm',
plugins: [
alias({
stream: require.resolve('readable-stream')
}),
nodeGlobals({buffer: true})
],
define: {
window: 'self',
global: 'self'
},
loader: {'.js': 'jsx'}
}
esbuild.build(buildOptions).then(() => console.log('build success.'))

View File

@@ -52,5 +52,7 @@ export function verifySignature(event) {
}
export async function signEvent(event, key) {
return secp256k1.schnorr.sign(getEventHash(event), key)
return Buffer.from(
await secp256k1.schnorr.sign(getEventHash(event), key)
).toString('hex')
}

View File

@@ -1,9 +1,10 @@
import * as secp256k1 from '@noble/secp256k1'
import {Buffer} from 'buffer'
export function generatePrivateKey() {
return Buffer.from(secp256k1.utils.randomPrivateKey()).toString('hex')
}
export function getPublicKey(privateKey) {
return secp256k1.schnorr.getPublicKey(privateKey)
return Buffer.from(secp256k1.schnorr.getPublicKey(privateKey)).toString('hex')
}

View File

@@ -15,11 +15,7 @@ export async function searchDomain(domain, query = '') {
export async function queryName(fullname) {
try {
let [name, domain] = fullname.split('@')
if (!domain) {
domain = name
name = '_'
}
if (!domain) return null
let res = await (
await fetch(`https://${domain}/.well-known/nostr.json?name=${name}`)

View File

@@ -1,6 +1,6 @@
{
"name": "nostr-tools",
"version": "0.21.4",
"version": "0.23.4",
"description": "Tools for making a Nostr client.",
"repository": {
"type": "git",
@@ -8,7 +8,7 @@
},
"dependencies": {
"@noble/hashes": "^0.5.7",
"@noble/secp256k1": "^1.3.0",
"@noble/secp256k1": "^1.5.2",
"browserify-cipher": ">=1",
"buffer": ">=5",
"create-hash": "^1.2.0",
@@ -30,7 +30,15 @@
"client"
],
"devDependencies": {
"@esbuild-plugins/node-globals-polyfill": "^0.1.1",
"esbuild": "^0.14.38",
"esbuild-plugin-alias": "^0.2.1",
"eslint": "^8.5.0",
"eslint-plugin-babel": "^5.3.1"
"eslint-plugin-babel": "^5.3.1",
"events": "^3.3.0",
"readable-stream": "^3.6.0"
},
"scripts": {
"prepublish": "node build.js"
}
}

20
pool.js
View File

@@ -26,32 +26,42 @@ export function relayPool() {
const activeSubscriptions = {}
const sub = ({cb, filter}, id = Math.random().toString().slice(2)) => {
const sub = ({cb, filter, beforeSend}, id) => {
if (!id) id = Math.random().toString().slice(2)
const subControllers = Object.fromEntries(
Object.values(relays)
.filter(({policy}) => policy.read)
.map(({relay}) => [
relay.url,
relay.sub({filter, cb: event => cb(event, relay.url)}, id)
relay.sub({cb: event => cb(event, relay.url), filter, beforeSend}, id)
])
)
const activeCallback = cb
const activeFilters = filter
const activeBeforeSend = beforeSend
const unsub = () => {
Object.values(subControllers).forEach(sub => sub.unsub())
delete activeSubscriptions[id]
}
const sub = ({cb = activeCallback, filter = activeFilters}) => {
const sub = ({
cb = activeCallback,
filter = activeFilters,
beforeSend = activeBeforeSend
}) => {
Object.entries(subControllers).map(([relayURL, sub]) => [
relayURL,
sub.sub({cb, filter}, id)
sub.sub({cb: event => cb(event, relayURL), filter, beforeSend}, id)
])
return activeSubscriptions[id]
}
const addRelay = relay => {
subControllers[relay.url] = relay.sub({cb, filter}, id)
subControllers[relay.url] = relay.sub(
{cb: event => cb(event, relay.url), filter, beforeSend},
id
)
return activeSubscriptions[id]
}
const removeRelay = relayURL => {

View File

@@ -119,7 +119,10 @@ export function relayConnect(url, onNotice = () => {}, onError = () => {}) {
ws.send(msg)
}
const sub = ({cb, filter}, channel = Math.random().toString().slice(2)) => {
const sub = (
{cb, filter, beforeSend},
channel = Math.random().toString().slice(2)
) => {
var filters = []
if (Array.isArray(filter)) {
filters = filter
@@ -127,16 +130,25 @@ export function relayConnect(url, onNotice = () => {}, onError = () => {}) {
filters.push(filter)
}
if (beforeSend) {
const beforeSendResult = beforeSend({filter, relay: url, channel})
filters = beforeSendResult.filter
}
trySend(['REQ', channel, ...filters])
channels[channel] = cb
openSubs[channel] = filters
const activeCallback = cb
const activeFilters = filters
const activeBeforeSend = beforeSend
return {
sub: ({cb = activeCallback, filter = activeFilters}) =>
sub({cb, filter}, channel),
sub: ({
cb = activeCallback,
filter = activeFilters,
beforeSend = activeBeforeSend
}) => sub({cb, filter, beforeSend}, channel),
unsub: () => {
delete openSubs[channel]
delete channels[channel]
@@ -160,7 +172,7 @@ export function relayConnect(url, onNotice = () => {}, onError = () => {}) {
unsub()
clearTimeout(willUnsub)
},
filter: {id: event.id}
filter: {ids: [event.id]}
},
`monitor-${event.id.slice(0, 5)}`
)