mirror of
https://github.com/nbd-wtf/nostr-tools.git
synced 2025-12-09 16:48:50 +00:00
Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9082953ede | ||
|
|
61f397463d | ||
|
|
312b6fd035 |
5
index.ts
5
index.ts
@@ -3,14 +3,15 @@ export * from './relay'
|
|||||||
export * from './event'
|
export * from './event'
|
||||||
export * from './filter'
|
export * from './filter'
|
||||||
|
|
||||||
export * as fj from './fakejson'
|
|
||||||
|
|
||||||
export * as nip04 from './nip04'
|
export * as nip04 from './nip04'
|
||||||
export * as nip05 from './nip05'
|
export * as nip05 from './nip05'
|
||||||
export * as nip06 from './nip06'
|
export * as nip06 from './nip06'
|
||||||
export * as nip19 from './nip19'
|
export * as nip19 from './nip19'
|
||||||
export * as nip26 from './nip26'
|
export * as nip26 from './nip26'
|
||||||
|
|
||||||
|
export * as fj from './fakejson'
|
||||||
|
export * as utils from './utils'
|
||||||
|
|
||||||
// monkey patch secp256k1
|
// monkey patch secp256k1
|
||||||
import * as secp256k1 from '@noble/secp256k1'
|
import * as secp256k1 from '@noble/secp256k1'
|
||||||
import {hmac} from '@noble/hashes/hmac'
|
import {hmac} from '@noble/hashes/hmac'
|
||||||
|
|||||||
2
nip05.ts
2
nip05.ts
@@ -36,7 +36,7 @@ export async function queryProfile(
|
|||||||
name = '_'
|
name = '_'
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!name.match(/^[a-z0-9-_]+$/)) return null
|
if (!name.match(/^[A-Za-z0-9-_]+$/)) return null
|
||||||
|
|
||||||
let res = await (
|
let res = await (
|
||||||
await _fetch(`https://${domain}/.well-known/nostr.json?name=${name}`)
|
await _fetch(`https://${domain}/.well-known/nostr.json?name=${name}`)
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "nostr-tools",
|
"name": "nostr-tools",
|
||||||
"version": "1.2.0",
|
"version": "1.2.1",
|
||||||
"description": "Tools for making a Nostr client.",
|
"description": "Tools for making a Nostr client.",
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
|
|||||||
8
relay.ts
8
relay.ts
@@ -46,7 +46,7 @@ export function relayInit(
|
|||||||
var listeners: {
|
var listeners: {
|
||||||
connect: Array<() => void>
|
connect: Array<() => void>
|
||||||
disconnect: Array<() => void>
|
disconnect: Array<() => void>
|
||||||
error: Array<() => void>
|
error: Array<(e: globalThis.Event) => void>
|
||||||
notice: Array<(msg: string) => void>
|
notice: Array<(msg: string) => void>
|
||||||
} = {
|
} = {
|
||||||
connect: [],
|
connect: [],
|
||||||
@@ -77,9 +77,9 @@ export function relayInit(
|
|||||||
setOpen()
|
setOpen()
|
||||||
resolve()
|
resolve()
|
||||||
}
|
}
|
||||||
ws.onerror = () => {
|
ws.onerror = (e: globalThis.Event) => {
|
||||||
listeners.error.forEach(cb => cb())
|
listeners.error.forEach(cb => cb(e))
|
||||||
reject()
|
reject(e)
|
||||||
}
|
}
|
||||||
ws.onclose = async () => {
|
ws.onclose = async () => {
|
||||||
listeners.disconnect.forEach(cb => cb())
|
listeners.disconnect.forEach(cb => cb())
|
||||||
|
|||||||
183
utils.test.js
Normal file
183
utils.test.js
Normal file
@@ -0,0 +1,183 @@
|
|||||||
|
/* eslint-env jest */
|
||||||
|
|
||||||
|
const {utils} = require('./lib/nostr.cjs')
|
||||||
|
|
||||||
|
const {insertEventIntoAscendingList, insertEventIntoDescendingList} = utils
|
||||||
|
|
||||||
|
describe('inserting into a desc sorted list of events', () => {
|
||||||
|
test('insert into an empty list', async () => {
|
||||||
|
const list0 = []
|
||||||
|
expect(
|
||||||
|
insertEventIntoDescendingList(list0, {id: 'abc', created_at: 10})
|
||||||
|
).toHaveLength(1)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('insert in the beginning of a list', async () => {
|
||||||
|
const list0 = [{created_at: 20}, {created_at: 10}]
|
||||||
|
const list1 = insertEventIntoDescendingList(list0, {
|
||||||
|
id: 'abc',
|
||||||
|
created_at: 30
|
||||||
|
})
|
||||||
|
expect(list1).toHaveLength(3)
|
||||||
|
expect(list1[0].id).toBe('abc')
|
||||||
|
})
|
||||||
|
|
||||||
|
test('insert in the beginning of a list with same created_at', async () => {
|
||||||
|
const list0 = [{created_at: 30}, {created_at: 20}, {created_at: 10}]
|
||||||
|
const list1 = insertEventIntoDescendingList(list0, {
|
||||||
|
id: 'abc',
|
||||||
|
created_at: 30
|
||||||
|
})
|
||||||
|
expect(list1).toHaveLength(4)
|
||||||
|
expect(list1[0].id).toBe('abc')
|
||||||
|
})
|
||||||
|
|
||||||
|
test('insert in the middle of a list', async () => {
|
||||||
|
const list0 = [
|
||||||
|
{created_at: 30},
|
||||||
|
{created_at: 20},
|
||||||
|
{created_at: 10},
|
||||||
|
{created_at: 1}
|
||||||
|
]
|
||||||
|
const list1 = insertEventIntoDescendingList(list0, {
|
||||||
|
id: 'abc',
|
||||||
|
created_at: 15
|
||||||
|
})
|
||||||
|
expect(list1).toHaveLength(5)
|
||||||
|
expect(list1[2].id).toBe('abc')
|
||||||
|
})
|
||||||
|
|
||||||
|
test('insert in the end of a list', async () => {
|
||||||
|
const list0 = [
|
||||||
|
{created_at: 20},
|
||||||
|
{created_at: 20},
|
||||||
|
{created_at: 20},
|
||||||
|
{created_at: 20},
|
||||||
|
{created_at: 10}
|
||||||
|
]
|
||||||
|
const list1 = insertEventIntoDescendingList(list0, {
|
||||||
|
id: 'abc',
|
||||||
|
created_at: 5
|
||||||
|
})
|
||||||
|
expect(list1).toHaveLength(6)
|
||||||
|
expect(list1.slice(-1)[0].id).toBe('abc')
|
||||||
|
})
|
||||||
|
|
||||||
|
test('insert in the last-to-end of a list with same created_at', async () => {
|
||||||
|
const list0 = [
|
||||||
|
{created_at: 20},
|
||||||
|
{created_at: 20},
|
||||||
|
{created_at: 20},
|
||||||
|
{created_at: 20},
|
||||||
|
{created_at: 10}
|
||||||
|
]
|
||||||
|
const list1 = insertEventIntoDescendingList(list0, {
|
||||||
|
id: 'abc',
|
||||||
|
created_at: 10
|
||||||
|
})
|
||||||
|
expect(list1).toHaveLength(6)
|
||||||
|
expect(list1.slice(-2)[0].id).toBe('abc')
|
||||||
|
})
|
||||||
|
|
||||||
|
test('do not insert duplicates', async () => {
|
||||||
|
const list0 = [
|
||||||
|
{created_at: 20},
|
||||||
|
{created_at: 20},
|
||||||
|
{created_at: 10, id: 'abc'}
|
||||||
|
]
|
||||||
|
const list1 = insertEventIntoDescendingList(list0, {
|
||||||
|
id: 'abc',
|
||||||
|
created_at: 10
|
||||||
|
})
|
||||||
|
expect(list1).toHaveLength(3)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('inserting into a asc sorted list of events', () => {
|
||||||
|
test('insert into an empty list', async () => {
|
||||||
|
const list0 = []
|
||||||
|
expect(
|
||||||
|
insertEventIntoAscendingList(list0, {id: 'abc', created_at: 10})
|
||||||
|
).toHaveLength(1)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('insert in the beginning of a list', async () => {
|
||||||
|
const list0 = [{created_at: 10}, {created_at: 20}]
|
||||||
|
const list1 = insertEventIntoAscendingList(list0, {
|
||||||
|
id: 'abc',
|
||||||
|
created_at: 1
|
||||||
|
})
|
||||||
|
expect(list1).toHaveLength(3)
|
||||||
|
expect(list1[0].id).toBe('abc')
|
||||||
|
})
|
||||||
|
|
||||||
|
test('insert in the beginning of a list with same created_at', async () => {
|
||||||
|
const list0 = [{created_at: 10}, {created_at: 20}, {created_at: 30}]
|
||||||
|
const list1 = insertEventIntoAscendingList(list0, {
|
||||||
|
id: 'abc',
|
||||||
|
created_at: 10
|
||||||
|
})
|
||||||
|
expect(list1).toHaveLength(4)
|
||||||
|
expect(list1[0].id).toBe('abc')
|
||||||
|
})
|
||||||
|
|
||||||
|
test('insert in the middle of a list', async () => {
|
||||||
|
const list0 = [
|
||||||
|
{created_at: 10},
|
||||||
|
{created_at: 20},
|
||||||
|
{created_at: 30},
|
||||||
|
{created_at: 40}
|
||||||
|
]
|
||||||
|
const list1 = insertEventIntoAscendingList(list0, {
|
||||||
|
id: 'abc',
|
||||||
|
created_at: 25
|
||||||
|
})
|
||||||
|
expect(list1).toHaveLength(5)
|
||||||
|
expect(list1[2].id).toBe('abc')
|
||||||
|
})
|
||||||
|
|
||||||
|
test('insert in the end of a list', async () => {
|
||||||
|
const list0 = [
|
||||||
|
{created_at: 20},
|
||||||
|
{created_at: 20},
|
||||||
|
{created_at: 20},
|
||||||
|
{created_at: 20},
|
||||||
|
{created_at: 40}
|
||||||
|
]
|
||||||
|
const list1 = insertEventIntoAscendingList(list0, {
|
||||||
|
id: 'abc',
|
||||||
|
created_at: 50
|
||||||
|
})
|
||||||
|
expect(list1).toHaveLength(6)
|
||||||
|
expect(list1.slice(-1)[0].id).toBe('abc')
|
||||||
|
})
|
||||||
|
|
||||||
|
test('insert in the last-to-end of a list with same created_at', async () => {
|
||||||
|
const list0 = [
|
||||||
|
{created_at: 20},
|
||||||
|
{created_at: 20},
|
||||||
|
{created_at: 20},
|
||||||
|
{created_at: 20},
|
||||||
|
{created_at: 30}
|
||||||
|
]
|
||||||
|
const list1 = insertEventIntoAscendingList(list0, {
|
||||||
|
id: 'abc',
|
||||||
|
created_at: 30
|
||||||
|
})
|
||||||
|
expect(list1).toHaveLength(6)
|
||||||
|
expect(list1.slice(-2)[0].id).toBe('abc')
|
||||||
|
})
|
||||||
|
|
||||||
|
test('do not insert duplicates', async () => {
|
||||||
|
const list0 = [
|
||||||
|
{created_at: 20},
|
||||||
|
{created_at: 20},
|
||||||
|
{created_at: 30, id: 'abc'}
|
||||||
|
]
|
||||||
|
const list1 = insertEventIntoAscendingList(list0, {
|
||||||
|
id: 'abc',
|
||||||
|
created_at: 30
|
||||||
|
})
|
||||||
|
expect(list1).toHaveLength(3)
|
||||||
|
})
|
||||||
|
})
|
||||||
95
utils.ts
95
utils.ts
@@ -1,2 +1,97 @@
|
|||||||
|
import {Event} from './event'
|
||||||
|
|
||||||
export const utf8Decoder = new TextDecoder('utf-8')
|
export const utf8Decoder = new TextDecoder('utf-8')
|
||||||
export const utf8Encoder = new TextEncoder()
|
export const utf8Encoder = new TextEncoder()
|
||||||
|
|
||||||
|
//
|
||||||
|
// fast insert-into-sorted-array functions adapted from https://github.com/terrymorse58/fast-sorted-array
|
||||||
|
//
|
||||||
|
export function insertEventIntoDescendingList(
|
||||||
|
sortedArray: Event[],
|
||||||
|
event: Event
|
||||||
|
) {
|
||||||
|
let start = 0
|
||||||
|
let end = sortedArray.length - 1
|
||||||
|
let midPoint
|
||||||
|
let position = start
|
||||||
|
|
||||||
|
if (end < 0) {
|
||||||
|
position = 0
|
||||||
|
} else if (event.created_at < sortedArray[end].created_at) {
|
||||||
|
position = end + 1
|
||||||
|
} else if (event.created_at >= sortedArray[start].created_at) {
|
||||||
|
position = start
|
||||||
|
} else
|
||||||
|
while (true) {
|
||||||
|
if (end <= start + 1) {
|
||||||
|
position = end
|
||||||
|
break
|
||||||
|
}
|
||||||
|
midPoint = Math.floor(start + (end - start) / 2)
|
||||||
|
if (sortedArray[midPoint].created_at > event.created_at) {
|
||||||
|
start = midPoint
|
||||||
|
} else if (sortedArray[midPoint].created_at < event.created_at) {
|
||||||
|
end = midPoint
|
||||||
|
} else {
|
||||||
|
// aMidPoint === num
|
||||||
|
position = midPoint
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// insert when num is NOT already in (no duplicates)
|
||||||
|
if (sortedArray[position]?.id !== event.id) {
|
||||||
|
return [
|
||||||
|
...sortedArray.slice(0, position),
|
||||||
|
event,
|
||||||
|
...sortedArray.slice(position)
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
return sortedArray
|
||||||
|
}
|
||||||
|
|
||||||
|
export function insertEventIntoAscendingList(
|
||||||
|
sortedArray: Event[],
|
||||||
|
event: Event
|
||||||
|
) {
|
||||||
|
let start = 0
|
||||||
|
let end = sortedArray.length - 1
|
||||||
|
let midPoint
|
||||||
|
let position = start
|
||||||
|
|
||||||
|
if (end < 0) {
|
||||||
|
position = 0
|
||||||
|
} else if (event.created_at > sortedArray[end].created_at) {
|
||||||
|
position = end + 1
|
||||||
|
} else if (event.created_at <= sortedArray[start].created_at) {
|
||||||
|
position = start
|
||||||
|
} else
|
||||||
|
while (true) {
|
||||||
|
if (end <= start + 1) {
|
||||||
|
position = end
|
||||||
|
break
|
||||||
|
}
|
||||||
|
midPoint = Math.floor(start + (end - start) / 2)
|
||||||
|
if (sortedArray[midPoint].created_at < event.created_at) {
|
||||||
|
start = midPoint
|
||||||
|
} else if (sortedArray[midPoint].created_at > event.created_at) {
|
||||||
|
end = midPoint
|
||||||
|
} else {
|
||||||
|
// aMidPoint === num
|
||||||
|
position = midPoint
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// insert when num is NOT already in (no duplicates)
|
||||||
|
if (sortedArray[position]?.id !== event.id) {
|
||||||
|
return [
|
||||||
|
...sortedArray.slice(0, position),
|
||||||
|
event,
|
||||||
|
...sortedArray.slice(position)
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
return sortedArray
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user