Compare commits
16 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| f872f9a54a | |||
| 9270e4ce41 | |||
| c7cc699881 | |||
| b19aab4c39 | |||
| b34809ff16 | |||
| 9ebb7c5179 | |||
| 99e98a82ba | |||
| bdb6dd195a | |||
| e0cb706d76 | |||
| 63c06622bf | |||
| 1100517392 | |||
| 2e36475f47 | |||
| 41d2ab7bba | |||
| f661499e77 | |||
| 9e7d548af3 | |||
| 4ba28b3927 |
+5
-2
@@ -5,5 +5,8 @@ MONGO_EXPLORER_URI=mongodb://127.0.0.1:27017/cooperative
|
||||
START_BLOCK=1
|
||||
FINISH_BLOCK=0xFFFFFFFF
|
||||
PORT=4000
|
||||
ACTIVATE_PARSER=0
|
||||
|
||||
ACTIVATE_PARSER=1
|
||||
REDIS_PORT=6379
|
||||
REDIS_HOST=localhost
|
||||
REDIS_PASSWORD==
|
||||
REDIS_STREAM_LIMIT=1000
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
FROM node:20-slim AS base
|
||||
|
||||
ENV PNPM_HOME="/pnpm"
|
||||
ENV PATH="$PNPM_HOME:$PATH"
|
||||
|
||||
RUN corepack enable
|
||||
|
||||
COPY . /app
|
||||
WORKDIR /app
|
||||
|
||||
FROM base AS prod-deps
|
||||
RUN --mount=type=cache,id=pnpm,target=/pnpm/store pnpm install --prod --frozen-lockfile
|
||||
|
||||
FROM base AS build
|
||||
RUN --mount=type=cache,id=pnpm,target=/pnpm/store pnpm install --frozen-lockfile
|
||||
RUN pnpm run build
|
||||
|
||||
FROM base
|
||||
COPY --from=prod-deps /app/node_modules /app/node_modules
|
||||
COPY --from=build /app/dist /app/dist
|
||||
|
||||
# Открываем порт
|
||||
EXPOSE 4000
|
||||
|
||||
# Запускаем приложение
|
||||
CMD ["npx", "esno", "src/index.ts"]
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
version: '3.8'
|
||||
|
||||
services:
|
||||
cooparser:
|
||||
container_name: cooparser
|
||||
build: ./
|
||||
image: cooparser
|
||||
env_file:
|
||||
- ./.env
|
||||
network_mode: host
|
||||
restart: unless-stopped
|
||||
Generated
+13
-13
@@ -1,29 +1,29 @@
|
||||
{
|
||||
"name": "pkg-placeholder",
|
||||
"version": "1.0.1",
|
||||
"version": "1.0.4",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "pkg-placeholder",
|
||||
"version": "1.0.1",
|
||||
"version": "1.0.4",
|
||||
"license": "MIT",
|
||||
"devDependencies": {
|
||||
"@antfu/eslint-config": "^2.6.4",
|
||||
"@antfu/eslint-config": "^2.16.0",
|
||||
"@antfu/ni": "^0.21.12",
|
||||
"@antfu/utils": "^0.7.7",
|
||||
"@types/node": "^20.11.19",
|
||||
"bumpp": "^9.3.0",
|
||||
"eslint": "^8.56.0",
|
||||
"esno": "^4.0.0",
|
||||
"@types/node": "^20.12.7",
|
||||
"bumpp": "^9.4.0",
|
||||
"eslint": "^8.57.0",
|
||||
"esno": "^4.7.0",
|
||||
"lint-staged": "^15.2.2",
|
||||
"pnpm": "^8.15.3",
|
||||
"pnpm": "^8.15.7",
|
||||
"rimraf": "^5.0.5",
|
||||
"simple-git-hooks": "^2.9.0",
|
||||
"typescript": "^5.3.3",
|
||||
"simple-git-hooks": "^2.11.1",
|
||||
"typescript": "^5.4.5",
|
||||
"unbuild": "^2.0.0",
|
||||
"vite": "^5.1.4",
|
||||
"vitest": "^1.3.1"
|
||||
"vite": "^5.2.10",
|
||||
"vitest": "^1.5.2"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/antfu"
|
||||
@@ -8902,4 +8902,4 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+5
-2
@@ -1,7 +1,8 @@
|
||||
{
|
||||
"name": "cooparser-ts",
|
||||
"type": "module",
|
||||
"version": "1.0.1",
|
||||
"version": "1.0.4",
|
||||
"private": true,
|
||||
"packageManager": "pnpm@9.0.6",
|
||||
"description": "",
|
||||
"author": "Alex Ant <dacom.dark.sun@gmail.com>",
|
||||
@@ -36,6 +37,8 @@
|
||||
"dist"
|
||||
],
|
||||
"scripts": {
|
||||
"deploy-testnet": "git checkout testnet && git merge main && git push origin testnet && git checkout main",
|
||||
"deploy-production": "git checkout production && git merge testnet && git push origin production && git checkout main",
|
||||
"build": "unbuild",
|
||||
"dev": "unbuild --stub",
|
||||
"lint": "eslint .",
|
||||
@@ -44,7 +47,6 @@
|
||||
"start": "esno src/index.ts",
|
||||
"test": "vitest",
|
||||
"typecheck": "tsc --noEmit",
|
||||
"prepare": "simple-git-hooks",
|
||||
"doc": "typedoc"
|
||||
},
|
||||
"dependencies": {
|
||||
@@ -55,6 +57,7 @@
|
||||
"eosjs": "^22.1.0",
|
||||
"express": "^4.19.2",
|
||||
"express-async-errors": "^3.1.1",
|
||||
"ioredis": "^5.4.1",
|
||||
"mongodb": "^6.5.0",
|
||||
"node-fetch": "^3.3.2",
|
||||
"typedoc": "^0.25.13",
|
||||
|
||||
Generated
+67
@@ -29,6 +29,9 @@ importers:
|
||||
express-async-errors:
|
||||
specifier: ^3.1.1
|
||||
version: 3.1.1(express@4.19.2)
|
||||
ioredis:
|
||||
specifier: ^5.4.1
|
||||
version: 5.4.1
|
||||
mongodb:
|
||||
specifier: ^6.5.0
|
||||
version: 6.5.0
|
||||
@@ -570,6 +573,9 @@ packages:
|
||||
'@humanwhocodes/object-schema@2.0.3':
|
||||
resolution: {integrity: sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==}
|
||||
|
||||
'@ioredis/commands@1.2.0':
|
||||
resolution: {integrity: sha512-Sx1pU8EM64o2BrqNpEO1CNLtKQwyhuXuqyfH7oGKCk+1a33d2r5saW8zNwm3j6BTExtjrv2BxTgzzkMwts6vGg==}
|
||||
|
||||
'@isaacs/cliui@8.0.2':
|
||||
resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==}
|
||||
engines: {node: '>=12'}
|
||||
@@ -1204,6 +1210,10 @@ packages:
|
||||
resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==}
|
||||
engines: {node: '>=12'}
|
||||
|
||||
cluster-key-slot@1.1.2:
|
||||
resolution: {integrity: sha512-RMr0FhtfXemyinomL4hrWcYJxmX6deFdCxpJzhDttxgO1+bcCnkk+9drydLVDmAMG7NE6aN/fl4F7ucU/90gAA==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
|
||||
color-convert@1.9.3:
|
||||
resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==}
|
||||
|
||||
@@ -1385,6 +1395,10 @@ packages:
|
||||
resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==}
|
||||
engines: {node: '>=0.4.0'}
|
||||
|
||||
denque@2.1.0:
|
||||
resolution: {integrity: sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==}
|
||||
engines: {node: '>=0.10'}
|
||||
|
||||
depd@2.0.0:
|
||||
resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==}
|
||||
engines: {node: '>= 0.8'}
|
||||
@@ -1973,6 +1987,10 @@ packages:
|
||||
inherits@2.0.4:
|
||||
resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==}
|
||||
|
||||
ioredis@5.4.1:
|
||||
resolution: {integrity: sha512-2YZsvl7jopIa1gaePkeMtd9rAcSjOOjPtpcLlOeusyO+XH2SK5ZcT+UCrElPP+WVIInh2TzeI4XW9ENaSLVVHA==}
|
||||
engines: {node: '>=12.22.0'}
|
||||
|
||||
ipaddr.js@1.9.1:
|
||||
resolution: {integrity: sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==}
|
||||
engines: {node: '>= 0.10'}
|
||||
@@ -2164,6 +2182,12 @@ packages:
|
||||
resolution: {integrity: sha512-gvVijfZvn7R+2qyPX8mAuKcFGDf6Nc61GdvGafQsHL0sBIxfKzA+usWn4GFC/bk+QdwPUD4kWFJLhElipq+0VA==}
|
||||
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
|
||||
|
||||
lodash.defaults@4.2.0:
|
||||
resolution: {integrity: sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ==}
|
||||
|
||||
lodash.isarguments@3.1.0:
|
||||
resolution: {integrity: sha512-chi4NHZlZqZD18a0imDHnZPrDeBbTtVN7GXMwuGdRH9qotxAjYs3aVLKc7zNOG9eddR5Ksd8rvFEBc9SsggPpg==}
|
||||
|
||||
lodash.memoize@4.1.2:
|
||||
resolution: {integrity: sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==}
|
||||
|
||||
@@ -2853,6 +2877,14 @@ packages:
|
||||
resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==}
|
||||
engines: {node: '>=8.10.0'}
|
||||
|
||||
redis-errors@1.2.0:
|
||||
resolution: {integrity: sha512-1qny3OExCf0UvUV/5wpYKf2YwPcOqXzkwKKSmKHiE6ZMQs5heeE/c8eXK+PNllPvmjgAbfnsbpkGZWy8cBpn9w==}
|
||||
engines: {node: '>=4'}
|
||||
|
||||
redis-parser@3.0.0:
|
||||
resolution: {integrity: sha512-DJnGAeenTdpMEH6uAJRK/uiyEIH9WVsUmoLwzudwGJUwZPp80PDBWPHXSAGNPwNvIXAbe7MSUB1zQFugFml66A==}
|
||||
engines: {node: '>=4'}
|
||||
|
||||
regexp-tree@0.1.27:
|
||||
resolution: {integrity: sha512-iETxpjK6YoRWJG5o6hXLwvjYAoW+FEZn9os0PD/b6AP6xQwsa/Y7lCVgIixBbUPMfhu+i2LtdeAqVTgGlQarfA==}
|
||||
hasBin: true
|
||||
@@ -3044,6 +3076,9 @@ packages:
|
||||
stackback@0.0.2:
|
||||
resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==}
|
||||
|
||||
standard-as-callback@2.1.0:
|
||||
resolution: {integrity: sha512-qoRRSyROncaz1z0mvYqIE4lCd9p2R90i6GxW3uZv5ucSu8tU7B5HXUP1gG8pVZsYNVaXjk8ClXHPttLyxAL48A==}
|
||||
|
||||
statuses@2.0.1:
|
||||
resolution: {integrity: sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==}
|
||||
engines: {node: '>= 0.8'}
|
||||
@@ -3878,6 +3913,8 @@ snapshots:
|
||||
|
||||
'@humanwhocodes/object-schema@2.0.3': {}
|
||||
|
||||
'@ioredis/commands@1.2.0': {}
|
||||
|
||||
'@isaacs/cliui@8.0.2':
|
||||
dependencies:
|
||||
string-width: 5.1.2
|
||||
@@ -4600,6 +4637,8 @@ snapshots:
|
||||
strip-ansi: 6.0.1
|
||||
wrap-ansi: 7.0.0
|
||||
|
||||
cluster-key-slot@1.1.2: {}
|
||||
|
||||
color-convert@1.9.3:
|
||||
dependencies:
|
||||
color-name: 1.1.3
|
||||
@@ -4777,6 +4816,8 @@ snapshots:
|
||||
|
||||
delayed-stream@1.0.0: {}
|
||||
|
||||
denque@2.1.0: {}
|
||||
|
||||
depd@2.0.0: {}
|
||||
|
||||
destr@2.0.3: {}
|
||||
@@ -5547,6 +5588,20 @@ snapshots:
|
||||
|
||||
inherits@2.0.4: {}
|
||||
|
||||
ioredis@5.4.1:
|
||||
dependencies:
|
||||
'@ioredis/commands': 1.2.0
|
||||
cluster-key-slot: 1.1.2
|
||||
debug: 4.3.4
|
||||
denque: 2.1.0
|
||||
lodash.defaults: 4.2.0
|
||||
lodash.isarguments: 3.1.0
|
||||
redis-errors: 1.2.0
|
||||
redis-parser: 3.0.0
|
||||
standard-as-callback: 2.1.0
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
ipaddr.js@1.9.1: {}
|
||||
|
||||
is-alphabetical@1.0.4: {}
|
||||
@@ -5715,6 +5770,10 @@ snapshots:
|
||||
dependencies:
|
||||
p-locate: 6.0.0
|
||||
|
||||
lodash.defaults@4.2.0: {}
|
||||
|
||||
lodash.isarguments@3.1.0: {}
|
||||
|
||||
lodash.memoize@4.1.2: {}
|
||||
|
||||
lodash.merge@4.6.2: {}
|
||||
@@ -6331,6 +6390,12 @@ snapshots:
|
||||
dependencies:
|
||||
picomatch: 2.3.1
|
||||
|
||||
redis-errors@1.2.0: {}
|
||||
|
||||
redis-parser@3.0.0:
|
||||
dependencies:
|
||||
redis-errors: 1.2.0
|
||||
|
||||
regexp-tree@0.1.27: {}
|
||||
|
||||
regjsparser@0.10.0:
|
||||
@@ -6541,6 +6606,8 @@ snapshots:
|
||||
|
||||
stackback@0.0.2: {}
|
||||
|
||||
standard-as-callback@2.1.0: {}
|
||||
|
||||
statuses@2.0.1: {}
|
||||
|
||||
std-env@3.7.0: {}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import type { Database } from '../../Database'
|
||||
import { publishEvent } from '../../RedisNotifier'
|
||||
import type { EosioShipReaderResolved, IAction } from '../../Types'
|
||||
import { subsribedActions } from '../../config'
|
||||
import { ActionParserFactory } from '../Factory/ActionFactory'
|
||||
|
||||
export async function ActionsParser(db: Database, reader: EosioShipReaderResolved) {
|
||||
@@ -9,8 +11,14 @@ export async function ActionsParser(db: Database, reader: EosioShipReaderResolve
|
||||
console.log(`\nACTION - account: ${action.account}, name: ${action.name}, authorization: ${JSON.stringify(action.authorization)}, data: ${JSON.stringify(action.data)}`)
|
||||
|
||||
const parser = ActionParserFactory.create(action.account, action.name)
|
||||
if (parser)
|
||||
const source = subsribedActions.find(el => el.action === action.name && el.code === action.account)
|
||||
|
||||
if (parser) {
|
||||
await parser.process(db, action)
|
||||
|
||||
if (source?.notify)
|
||||
await publishEvent('action', action)
|
||||
}
|
||||
})
|
||||
|
||||
console.log('Подписка на действия активирована')
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import type { Database } from '../../Database'
|
||||
import { publishEvent } from '../../RedisNotifier'
|
||||
import type { EosioShipReaderResolved, IDelta } from '../../Types'
|
||||
import { subsribedTables } from '../../config'
|
||||
import { DeltaParserFactory } from '../Factory'
|
||||
|
||||
export async function DeltasParser(db: Database, reader: EosioShipReaderResolved) {
|
||||
@@ -7,10 +9,15 @@ export async function DeltasParser(db: Database, reader: EosioShipReaderResolved
|
||||
|
||||
rows$.subscribe(async (delta: IDelta) => {
|
||||
console.log(`\nDELTA - code: ${delta.code}, scope: ${delta.scope}, table: ${delta.table}, primary_key: ${delta.primary_key}, data: ${JSON.stringify(delta.value)}`)
|
||||
const source = subsribedTables.find(el => el.code === delta.code && el.table === delta.table)
|
||||
|
||||
const parser = DeltaParserFactory.create(delta.code, delta.scope, delta.table)
|
||||
if (parser)
|
||||
if (parser) {
|
||||
await parser.process(db, delta)
|
||||
|
||||
if (source?.notify)
|
||||
await publishEvent('delta', delta)
|
||||
}
|
||||
})
|
||||
|
||||
console.log('Подписка на дельты активирована')
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
import Redis from 'ioredis'
|
||||
import { redisHost, redisPassword, redisPort, redisStreamLimit } from '../config'
|
||||
|
||||
// const redis = new Redis(redisPort)
|
||||
|
||||
const redis = new Redis({
|
||||
port: Number(redisPort),
|
||||
host: redisHost,
|
||||
password: redisPassword,
|
||||
// другие опции при необходимости
|
||||
})
|
||||
|
||||
const streamName = 'notifications'
|
||||
|
||||
export async function publishEvent(type: string, event: object) {
|
||||
const message = JSON.stringify({ type, event })
|
||||
|
||||
await redis.xadd(streamName, '*', 'event', message)
|
||||
await redis.xtrim(streamName, 'MAXLEN', '~', redisStreamLimit)
|
||||
}
|
||||
@@ -8,6 +8,19 @@ export { EosioReaderAction as IAction } from '@blockmatic/eosio-ship-reader'
|
||||
export type EosioShipReader = ReturnType<typeof createEosioShipReader>
|
||||
export type EosioShipReaderResolved = Awaited<EosioShipReader>
|
||||
|
||||
export interface IDeltaConfig {
|
||||
code: string
|
||||
table: string
|
||||
scope?: string
|
||||
notify?: boolean
|
||||
}
|
||||
|
||||
export interface IActionConfig {
|
||||
code: string
|
||||
action: string
|
||||
notify?: boolean
|
||||
}
|
||||
|
||||
export interface IParserDelta {
|
||||
process: (db: Database, delta: IDelta) => Promise<void>
|
||||
}
|
||||
|
||||
+10
-3
@@ -1,4 +1,5 @@
|
||||
import dotenv from 'dotenv'
|
||||
import type { IActionConfig, IDeltaConfig } from './Types'
|
||||
|
||||
dotenv.config()
|
||||
|
||||
@@ -15,9 +16,12 @@ export const shipApi = getEnvVar('SHIP')
|
||||
export const mongoUri = getEnvVar('MONGO_EXPLORER_URI')
|
||||
export const startBlock = getEnvVar('START_BLOCK')
|
||||
export const finishBlock = getEnvVar('FINISH_BLOCK')
|
||||
|
||||
export const redisPort = getEnvVar('REDIS_PORT')
|
||||
export const redisHost = getEnvVar('REDIS_HOST')
|
||||
export const redisPassword = getEnvVar('REDIS_PASSWORD')
|
||||
export const redisStreamLimit = Number(getEnvVar('REDIS_STREAM_LIMIT'))
|
||||
// --------------------------
|
||||
export const subsribedTables = [
|
||||
export const subsribedTables: IDeltaConfig[] = [
|
||||
// документы
|
||||
{ code: 'draft', table: 'drafts' },
|
||||
{ code: 'draft', table: 'translations' },
|
||||
@@ -35,7 +39,10 @@ export const subsribedTables = [
|
||||
{ code: 'registrator', table: 'orgs' },
|
||||
]
|
||||
|
||||
export const subsribedActions = [
|
||||
export const subsribedActions: IActionConfig[] = [
|
||||
{ code: 'eosio.token', action: 'transfer', notify: true },
|
||||
{ code: 'registrator', action: 'confirmreg', notify: true },
|
||||
|
||||
{ code: 'soviet', action: 'votefor' },
|
||||
{ code: 'soviet', action: 'voteagainst' },
|
||||
{ code: 'soviet', action: 'newsubmitted' },
|
||||
|
||||
Reference in New Issue
Block a user