mirror of
https://github.com/nbd-wtf/nostr-tools.git
synced 2025-12-09 16:48:50 +00:00
Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
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'
|
||||||
|
|||||||
@@ -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",
|
||||||
|
|||||||
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