mirror of
https://github.com/Cameri/nostream.git
synced 2025-09-17 19:13:35 +02:00
fix: type errors
This commit is contained in:
@@ -15,3 +15,4 @@ Dockerfile
|
||||
*.md
|
||||
.nostr
|
||||
postgresql.conf
|
||||
test/integration/docker-compose.yml
|
@@ -53,4 +53,4 @@ RUN npm install --omit=dev --quiet
|
||||
|
||||
USER 1000:1000
|
||||
|
||||
CMD ["node", "src/index.js"]
|
||||
CMD ["node", "src/index.js"]
|
||||
|
@@ -10,11 +10,11 @@ ENV DB_MAX_POOL_SIZE=2
|
||||
ENV REDIS_HOST=cache-test
|
||||
ENV REDIS_PORT=6379
|
||||
ENV REDIS_USER=default
|
||||
ENV REDIS_PASSWORD=nostr_ts_relay
|
||||
ENV REDIS_PASSWORD=nostr_ts_relay_test
|
||||
|
||||
WORKDIR /code
|
||||
|
||||
COPY ["package.json", "settings.sample.json", "package-lock.json", ".nycrc.json", ".mocharc.js", "cucumber.js", "tsconfig.json", "knexfile.js", "./"]
|
||||
COPY ["package.json", "package-lock.json", "./"]
|
||||
|
||||
RUN npm install --quiet
|
||||
|
||||
|
@@ -3,7 +3,7 @@ services:
|
||||
build: .
|
||||
container_name: nostr-ts-relay
|
||||
environment:
|
||||
PORT: 8008
|
||||
RELAY_PORT: 8008
|
||||
NOSTR_CONFIG_DIR: /home/node/
|
||||
DB_HOST: db
|
||||
DB_PORT: 5432
|
||||
|
@@ -19,7 +19,7 @@ export class AppWorker implements IRunnable {
|
||||
}
|
||||
|
||||
public run(): void {
|
||||
const port = Number(process.env.PORT) || 8008
|
||||
const port = Number(process.env.RELAY_PORT) || 8008
|
||||
|
||||
this.adapter.listen(port)
|
||||
}
|
||||
|
4
src/cache/client.ts
vendored
4
src/cache/client.ts
vendored
@@ -6,12 +6,14 @@ export const getCacheConfig = (): RedisClientOptions => ({
|
||||
password: process.env.REDIS_PASSWORD,
|
||||
})
|
||||
|
||||
let instance: CacheClient = undefined
|
||||
let instance: CacheClient | undefined = undefined
|
||||
|
||||
export const getCacheClient = (): CacheClient => {
|
||||
if (!instance) {
|
||||
const config = getCacheConfig()
|
||||
|
||||
console.log(config)
|
||||
|
||||
instance = createClient(config)
|
||||
}
|
||||
|
||||
|
@@ -13,11 +13,11 @@ export const workerFactory = (): AppWorker => {
|
||||
const dbClient = getDbClient()
|
||||
const eventRepository = new EventRepository(dbClient)
|
||||
|
||||
// deepcode ignore HttpToHttps: <please specify a reason of ignoring this>
|
||||
// deepcode ignore HttpToHttps: we use proxies
|
||||
const server = http.createServer()
|
||||
const webSocketServer = new WebSocketServer({
|
||||
server,
|
||||
maxPayload: 1024 * 1024,
|
||||
maxPayload: 102400, // 0.1 MB
|
||||
})
|
||||
const adapter = new WebSocketServerAdapter(
|
||||
server,
|
||||
|
@@ -1,8 +1,8 @@
|
||||
import * as secp256k1 from '@noble/secp256k1'
|
||||
import { applySpec, converge, curry, mergeLeft, nth, omit, pipe, prop, reduceBy } from 'ramda'
|
||||
|
||||
import { CanonicalEvent, Event } from '../@types/event'
|
||||
import { EventId, Pubkey } from '../@types/base'
|
||||
import { CanonicalEvent, DBEvent, Event } from '../@types/event'
|
||||
import { EventId, Pubkey, Tag } from '../@types/base'
|
||||
import { EventKinds, EventTags } from '../constants/base'
|
||||
import { fromBuffer } from './transform'
|
||||
import { getLeadingZeroBits } from './proof-of-work'
|
||||
@@ -10,7 +10,7 @@ import { isGenericTagQuery } from './filter'
|
||||
import { RuneLike } from './runes/rune-like'
|
||||
import { SubscriptionFilter } from '../@types/subscription'
|
||||
|
||||
export const serializeEvent = (event: Partial<Event>): CanonicalEvent => [
|
||||
export const serializeEvent = (event: Event): CanonicalEvent => [
|
||||
0,
|
||||
event.pubkey,
|
||||
event.created_at,
|
||||
@@ -19,18 +19,18 @@ export const serializeEvent = (event: Partial<Event>): CanonicalEvent => [
|
||||
event.content,
|
||||
]
|
||||
|
||||
export const toNostrEvent = applySpec({
|
||||
id: pipe(prop('event_id'), fromBuffer),
|
||||
kind: prop('event_kind'),
|
||||
pubkey: pipe(prop('event_pubkey'), fromBuffer),
|
||||
created_at: prop('event_created_at'),
|
||||
content: prop('event_content'),
|
||||
tags: prop('event_tags'),
|
||||
sig: pipe(prop('event_signature'), fromBuffer),
|
||||
export const toNostrEvent: (event: DBEvent) => Event = applySpec({
|
||||
id: pipe(prop('event_id') as () => Buffer, fromBuffer),
|
||||
kind: prop('event_kind') as () => number,
|
||||
pubkey: pipe(prop('event_pubkey') as () => Buffer, fromBuffer),
|
||||
created_at: prop('event_created_at') as () => number,
|
||||
content: prop('event_content') as () => string,
|
||||
tags: prop('event_tags') as () => Tag[],
|
||||
sig: pipe(prop('event_signature') as () => Buffer, fromBuffer),
|
||||
})
|
||||
|
||||
export const isEventMatchingFilter = (filter: SubscriptionFilter) => (event: Event): boolean => {
|
||||
const startsWith = (input: string) => (prefix) => input.startsWith(prefix)
|
||||
const startsWith = (input: string) => (prefix: string) => input.startsWith(prefix)
|
||||
|
||||
// NIP-01: Basic protocol flow description
|
||||
|
||||
@@ -58,6 +58,9 @@ export const isEventMatchingFilter = (filter: SubscriptionFilter) => (event: Eve
|
||||
) {
|
||||
if (isDelegatedEvent(event)) {
|
||||
const delegation = event.tags.find((tag) => tag[0] === EventTags.Delegation)
|
||||
if (typeof delegation === 'undefined') {
|
||||
return false
|
||||
}
|
||||
|
||||
if (!filter.authors.some(startsWith(delegation[1]))) {
|
||||
return false
|
||||
@@ -119,10 +122,10 @@ export const isDelegatedEventValid = async (event: Event): Promise<boolean> => {
|
||||
omit(['tags']),
|
||||
pipe(
|
||||
prop('tags') as any,
|
||||
reduceBy(
|
||||
reduceBy<EventTags, string[]>(
|
||||
(acc, tag) => ([...acc, tag[1]]),
|
||||
[],
|
||||
nth(0),
|
||||
nth(0) as any,
|
||||
),
|
||||
),
|
||||
],
|
||||
|
@@ -2,7 +2,7 @@ import { IAlternative } from '../../@types/runes'
|
||||
|
||||
const punctuations = /[!"#$%&'()*+-./:;<=>?@[\\\]^`{|}~]/
|
||||
|
||||
const hasPunctuation = (input) => punctuations.test(input)
|
||||
const hasPunctuation = (input: string) => punctuations.test(input)
|
||||
|
||||
// Reference: https://github.com/rustyrussell/runes/blob/master/runes/runes.py
|
||||
|
||||
|
@@ -4,6 +4,7 @@ services:
|
||||
context: ../../
|
||||
dockerfile: Dockerfile.test
|
||||
environment:
|
||||
RELAY_PORT: 18808
|
||||
DB_HOST: db-test
|
||||
DB_PORT: 5432
|
||||
DB_NAME: nostr_ts_relay_test
|
||||
@@ -17,10 +18,14 @@ services:
|
||||
REDIS_PASSWORD: nostr_ts_relay_test
|
||||
NOSTR_CONFIG_DIR: /code
|
||||
volumes:
|
||||
- ../../package.json:/code/package.json
|
||||
- ../../settings.sample.json:/code/settings.sample.json
|
||||
- ../../src:/code/src
|
||||
- ../../test:/code/test
|
||||
- ../../test/integration:/code/test/integration
|
||||
- ../../cucumber.js:/code/cucumber.js
|
||||
- ../../.coverage:/code/.coverage
|
||||
- ../../.test-reports:/code/.test-reports
|
||||
- ../../tsconfig.json:/code/tsconfig.json
|
||||
working_dir: /code
|
||||
depends_on:
|
||||
cache-test:
|
||||
|
@@ -1,6 +1,6 @@
|
||||
import * as secp256k1 from '@noble/secp256k1'
|
||||
import { createHash, createHmac, Hash } from 'crypto'
|
||||
import WebSocket, { RawData } from 'ws'
|
||||
import { createHmac } from 'crypto'
|
||||
|
||||
import { Event } from '../../../src/@types/event'
|
||||
import { MessageType } from '../../../src/@types/messages'
|
||||
@@ -8,6 +8,9 @@ import { serializeEvent } from '../../../src/utils/event'
|
||||
import { SubscriptionFilter } from '../../../src/@types/subscription'
|
||||
|
||||
|
||||
secp256k1.utils.sha256Sync = (...messages: Uint8Array[]) =>
|
||||
messages.reduce((hash: Hash, message: Uint8Array) => hash.update(message), createHash('sha256')).digest()
|
||||
|
||||
export async function connect(_name: string) {
|
||||
const host = 'ws://localhost:18808'
|
||||
const ws = new WebSocket(host)
|
||||
@@ -35,17 +38,18 @@ export async function createEvent(input: Partial<Event>, privkey: any): Promise<
|
||||
tags: input.tags ?? [],
|
||||
} as any
|
||||
|
||||
const id = Buffer.from(
|
||||
await secp256k1.utils.sha256(
|
||||
Buffer.from(JSON.stringify(serializeEvent(event)))
|
||||
)
|
||||
).toString('hex')
|
||||
const id = createHash('sha256').update(
|
||||
Buffer.from(JSON.stringify(serializeEvent(event)))
|
||||
).digest().toString('hex')
|
||||
|
||||
const sig = Buffer.from(
|
||||
await secp256k1.schnorr.sign(id, privkey)
|
||||
secp256k1.schnorr.signSync(id, privkey)
|
||||
).toString('hex')
|
||||
|
||||
return { id, ...event, sig }
|
||||
event.id = id
|
||||
event.sig = sig
|
||||
|
||||
return event
|
||||
}
|
||||
|
||||
export function createIdentity(name: string) {
|
||||
@@ -73,7 +77,7 @@ export async function createSubscription(
|
||||
...subscriptionFilters,
|
||||
])
|
||||
|
||||
ws.send(message, (error: Error) => {
|
||||
ws.send(message, (error?: Error) => {
|
||||
if (error) {
|
||||
reject(error)
|
||||
return
|
||||
@@ -157,7 +161,7 @@ export async function waitForEventCount(
|
||||
count = 1,
|
||||
eose = false,
|
||||
): Promise<Event[]> {
|
||||
const events = []
|
||||
const events: Event[] = []
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
ws.on('message', onMessage)
|
||||
|
@@ -8,6 +8,7 @@ import {
|
||||
When,
|
||||
World,
|
||||
} from '@cucumber/cucumber'
|
||||
import { assocPath } from 'ramda'
|
||||
import WebSocket from 'ws'
|
||||
|
||||
import { connect, createIdentity, createSubscription } from './helpers'
|
||||
@@ -25,13 +26,14 @@ let dbClient: DatabaseClient
|
||||
let cacheClient: CacheClient
|
||||
|
||||
BeforeAll({ timeout: 6000 }, async function () {
|
||||
process.env.PORT = '18808'
|
||||
process.env.RELAY_PORT = '18808'
|
||||
cacheClient = getCacheClient()
|
||||
dbClient = getDbClient()
|
||||
await dbClient.raw('SELECT 1=1')
|
||||
|
||||
const limits = SettingsStatic.createSettings().limits
|
||||
limits.event.createdAt.maxPositiveDelta = 0
|
||||
const { limits } = SettingsStatic.createSettings()
|
||||
|
||||
assocPath(['event', 'createdAt', 'maxPositiveDelta'], 0)(limits)
|
||||
|
||||
worker = workerFactory()
|
||||
worker.run()
|
||||
@@ -56,18 +58,18 @@ Before(async function () {
|
||||
After(async function () {
|
||||
this.parameters.events = {}
|
||||
this.parameters.subscriptions = {}
|
||||
Object.values(this.parameters.clients).forEach((ws: WebSocket) => {
|
||||
for (const ws of Object.values(this.parameters.clients as Record<string, WebSocket>)) {
|
||||
if (ws && ws.readyState === WebSocket.OPEN) {
|
||||
ws.close()
|
||||
}
|
||||
})
|
||||
}
|
||||
this.parameters.clients = {}
|
||||
|
||||
const dbClient = getDbClient()
|
||||
await Promise.all(
|
||||
Object.values(this.parameters.identities)
|
||||
.map(async (identity: { pubkey: string }) => dbClient('events').where({ event_pubkey: Buffer.from(identity.pubkey, 'hex') }).del())
|
||||
)
|
||||
|
||||
for (const identity of Object.values(this.parameters.identities as Record<string, { pubkey: string }>)) {
|
||||
await dbClient('events').where({ event_pubkey: Buffer.from(identity.pubkey, 'hex') }).del()
|
||||
}
|
||||
this.parameters.identities = {}
|
||||
})
|
||||
|
||||
|
@@ -68,7 +68,7 @@ describe('messageHandlerFactory', () => {
|
||||
})
|
||||
|
||||
it('throws when given an invalid message', () => {
|
||||
message = []
|
||||
message = [] as any
|
||||
|
||||
expect(() => factory([message, adapter])).to.throw(Error, 'Unknown message type: undefined')
|
||||
})
|
||||
|
@@ -19,9 +19,6 @@
|
||||
"esModuleInterop": true,
|
||||
"lib": ["ESNext"]
|
||||
},
|
||||
"ts-node": {
|
||||
"transpileOnly": true
|
||||
},
|
||||
"include": [
|
||||
"src/**/*.ts",
|
||||
"test/**/*.ts"
|
||||
|
Reference in New Issue
Block a user