@trading-boy/core 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +8 -0
- package/dist/.gitkeep +0 -0
- package/dist/config/env.d.ts +102 -0
- package/dist/config/env.d.ts.map +1 -0
- package/dist/config/env.js +178 -0
- package/dist/config/env.js.map +1 -0
- package/dist/config/index.d.ts +2 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/index.js +2 -0
- package/dist/config/index.js.map +1 -0
- package/dist/constants/index.d.ts +49 -0
- package/dist/constants/index.d.ts.map +1 -0
- package/dist/constants/index.js +63 -0
- package/dist/constants/index.js.map +1 -0
- package/dist/crypto.d.ts +47 -0
- package/dist/crypto.d.ts.map +1 -0
- package/dist/crypto.js +56 -0
- package/dist/crypto.js.map +1 -0
- package/dist/errors/index.d.ts +25 -0
- package/dist/errors/index.d.ts.map +1 -0
- package/dist/errors/index.js +50 -0
- package/dist/errors/index.js.map +1 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +13 -0
- package/dist/index.js.map +1 -0
- package/dist/llm/client.d.ts +38 -0
- package/dist/llm/client.d.ts.map +1 -0
- package/dist/llm/client.js +194 -0
- package/dist/llm/client.js.map +1 -0
- package/dist/llm/config.d.ts +12 -0
- package/dist/llm/config.d.ts.map +1 -0
- package/dist/llm/config.js +47 -0
- package/dist/llm/config.js.map +1 -0
- package/dist/llm/index.d.ts +5 -0
- package/dist/llm/index.d.ts.map +1 -0
- package/dist/llm/index.js +4 -0
- package/dist/llm/index.js.map +1 -0
- package/dist/llm/structured-output.d.ts +31 -0
- package/dist/llm/structured-output.d.ts.map +1 -0
- package/dist/llm/structured-output.js +69 -0
- package/dist/llm/structured-output.js.map +1 -0
- package/dist/llm/types.d.ts +39 -0
- package/dist/llm/types.d.ts.map +1 -0
- package/dist/llm/types.js +6 -0
- package/dist/llm/types.js.map +1 -0
- package/dist/logging/index.d.ts +2 -0
- package/dist/logging/index.d.ts.map +1 -0
- package/dist/logging/index.js +2 -0
- package/dist/logging/index.js.map +1 -0
- package/dist/logging/logger.d.ts +7 -0
- package/dist/logging/logger.d.ts.map +1 -0
- package/dist/logging/logger.js +66 -0
- package/dist/logging/logger.js.map +1 -0
- package/dist/types/context-package.d.ts +100 -0
- package/dist/types/context-package.d.ts.map +1 -0
- package/dist/types/context-package.js +2 -0
- package/dist/types/context-package.js.map +1 -0
- package/dist/types/daily-summary.d.ts +212 -0
- package/dist/types/daily-summary.d.ts.map +1 -0
- package/dist/types/daily-summary.js +6 -0
- package/dist/types/daily-summary.js.map +1 -0
- package/dist/types/decision-traces.d.ts +123 -0
- package/dist/types/decision-traces.d.ts.map +1 -0
- package/dist/types/decision-traces.js +2 -0
- package/dist/types/decision-traces.js.map +1 -0
- package/dist/types/enums.d.ts +207 -0
- package/dist/types/enums.d.ts.map +1 -0
- package/dist/types/enums.js +247 -0
- package/dist/types/enums.js.map +1 -0
- package/dist/types/graph-edges.d.ts +127 -0
- package/dist/types/graph-edges.d.ts.map +1 -0
- package/dist/types/graph-edges.js +3 -0
- package/dist/types/graph-edges.js.map +1 -0
- package/dist/types/graph-nodes.d.ts +79 -0
- package/dist/types/graph-nodes.d.ts.map +1 -0
- package/dist/types/graph-nodes.js +2 -0
- package/dist/types/graph-nodes.js.map +1 -0
- package/package.json +31 -0
package/README.md
ADDED
package/dist/.gitkeep
ADDED
|
File without changes
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
declare const envSchema: z.ZodObject<{
|
|
3
|
+
NODE_ENV: z.ZodDefault<z.ZodEnum<{
|
|
4
|
+
development: "development";
|
|
5
|
+
production: "production";
|
|
6
|
+
test: "test";
|
|
7
|
+
}>>;
|
|
8
|
+
LOG_LEVEL: z.ZodDefault<z.ZodEnum<{
|
|
9
|
+
trace: "trace";
|
|
10
|
+
debug: "debug";
|
|
11
|
+
info: "info";
|
|
12
|
+
warn: "warn";
|
|
13
|
+
error: "error";
|
|
14
|
+
fatal: "fatal";
|
|
15
|
+
}>>;
|
|
16
|
+
NEO4J_URI: z.ZodDefault<z.ZodString>;
|
|
17
|
+
NEO4J_USER: z.ZodDefault<z.ZodString>;
|
|
18
|
+
NEO4J_PASSWORD: z.ZodDefault<z.ZodString>;
|
|
19
|
+
TIMESCALE_HOST: z.ZodDefault<z.ZodString>;
|
|
20
|
+
TIMESCALE_PORT: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
|
|
21
|
+
TIMESCALE_USER: z.ZodDefault<z.ZodString>;
|
|
22
|
+
TIMESCALE_PASSWORD: z.ZodDefault<z.ZodString>;
|
|
23
|
+
TIMESCALE_DB: z.ZodDefault<z.ZodString>;
|
|
24
|
+
REDIS_URL: z.ZodDefault<z.ZodString>;
|
|
25
|
+
REDIS_PASSWORD: z.ZodDefault<z.ZodString>;
|
|
26
|
+
JUPITER_API_KEY: z.ZodDefault<z.ZodString>;
|
|
27
|
+
HELIUS_API_KEY: z.ZodDefault<z.ZodString>;
|
|
28
|
+
COINGECKO_API_KEY: z.ZodDefault<z.ZodString>;
|
|
29
|
+
ALCHEMY_API_KEY: z.ZodDefault<z.ZodString>;
|
|
30
|
+
GLASSNODE_API_KEY: z.ZodDefault<z.ZodString>;
|
|
31
|
+
TWITTER_BEARER_TOKEN: z.ZodDefault<z.ZodString>;
|
|
32
|
+
ANTHROPIC_API_KEY: z.ZodDefault<z.ZodString>;
|
|
33
|
+
LLM_PROVIDER: z.ZodDefault<z.ZodEnum<{
|
|
34
|
+
anthropic: "anthropic";
|
|
35
|
+
openrouter: "openrouter";
|
|
36
|
+
ollama: "ollama";
|
|
37
|
+
custom: "custom";
|
|
38
|
+
}>>;
|
|
39
|
+
LLM_API_KEY: z.ZodDefault<z.ZodString>;
|
|
40
|
+
LLM_BASE_URL: z.ZodDefault<z.ZodString>;
|
|
41
|
+
LLM_MODEL: z.ZodDefault<z.ZodString>;
|
|
42
|
+
LLM_FALLBACK_PROVIDER: z.ZodDefault<z.ZodString>;
|
|
43
|
+
LLM_FALLBACK_MODEL: z.ZodDefault<z.ZodString>;
|
|
44
|
+
LLM_FALLBACK_API_KEY: z.ZodDefault<z.ZodString>;
|
|
45
|
+
LLM_MAX_RETRIES: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
|
|
46
|
+
LLM_TIMEOUT_MS: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
|
|
47
|
+
BELIEF_HMAC_KEY: z.ZodDefault<z.ZodString>;
|
|
48
|
+
ENABLE_LLM: z.ZodPipe<z.ZodDefault<z.ZodEnum<{
|
|
49
|
+
true: "true";
|
|
50
|
+
false: "false";
|
|
51
|
+
}>>, z.ZodTransform<boolean, "true" | "false">>;
|
|
52
|
+
ENABLE_LEARNING: z.ZodPipe<z.ZodDefault<z.ZodEnum<{
|
|
53
|
+
true: "true";
|
|
54
|
+
false: "false";
|
|
55
|
+
}>>, z.ZodTransform<boolean, "true" | "false">>;
|
|
56
|
+
ENABLE_SOCIAL: z.ZodPipe<z.ZodDefault<z.ZodEnum<{
|
|
57
|
+
true: "true";
|
|
58
|
+
false: "false";
|
|
59
|
+
}>>, z.ZodTransform<boolean, "true" | "false">>;
|
|
60
|
+
API_PORT: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
|
|
61
|
+
TELEGRAM_BOT_TOKEN: z.ZodDefault<z.ZodString>;
|
|
62
|
+
TELEGRAM_ALLOWED_CHAT_IDS: z.ZodDefault<z.ZodString>;
|
|
63
|
+
RESEND_API_KEY: z.ZodDefault<z.ZodString>;
|
|
64
|
+
EMAIL_FROM_ADDRESS: z.ZodDefault<z.ZodString>;
|
|
65
|
+
EMAIL_FROM_NAME: z.ZodDefault<z.ZodString>;
|
|
66
|
+
SMTP_HOST: z.ZodDefault<z.ZodString>;
|
|
67
|
+
SMTP_PORT: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
|
|
68
|
+
SMTP_USER: z.ZodDefault<z.ZodString>;
|
|
69
|
+
SMTP_PASS: z.ZodDefault<z.ZodString>;
|
|
70
|
+
NOTIFICATION_FROM_EMAIL: z.ZodDefault<z.ZodString>;
|
|
71
|
+
STRIPE_SECRET_KEY: z.ZodDefault<z.ZodString>;
|
|
72
|
+
STRIPE_WEBHOOK_SECRET: z.ZodDefault<z.ZodString>;
|
|
73
|
+
STRIPE_PRICE_ID: z.ZodDefault<z.ZodString>;
|
|
74
|
+
APP_URL: z.ZodDefault<z.ZodString>;
|
|
75
|
+
API_KEY_HASHES: z.ZodDefault<z.ZodString>;
|
|
76
|
+
API_KEY_AUTH_ENABLED: z.ZodPipe<z.ZodDefault<z.ZodEnum<{
|
|
77
|
+
true: "true";
|
|
78
|
+
false: "false";
|
|
79
|
+
}>>, z.ZodTransform<boolean, "true" | "false">>;
|
|
80
|
+
}, z.core.$strip>;
|
|
81
|
+
export type Config = z.infer<typeof envSchema>;
|
|
82
|
+
/**
|
|
83
|
+
* Parse and validate environment variables. Returns a cached Config singleton.
|
|
84
|
+
*
|
|
85
|
+
* In production mode, NEO4J_PASSWORD, TIMESCALE_PASSWORD, and REDIS_PASSWORD
|
|
86
|
+
* must be explicitly set to non-default values. In development/test mode,
|
|
87
|
+
* defaults are used so the system works out of the box.
|
|
88
|
+
*
|
|
89
|
+
* @throws {ConfigError} if validation fails
|
|
90
|
+
*/
|
|
91
|
+
export declare function getConfig(): Config;
|
|
92
|
+
/**
|
|
93
|
+
* Reset the config singleton. Used in tests to re-parse environment variables.
|
|
94
|
+
* @internal
|
|
95
|
+
*/
|
|
96
|
+
export declare function resetConfig(): void;
|
|
97
|
+
/**
|
|
98
|
+
* Build a PostgreSQL connection string from individual TimescaleDB config fields.
|
|
99
|
+
*/
|
|
100
|
+
export declare function getTimescaleConnectionString(config: Config): string;
|
|
101
|
+
export {};
|
|
102
|
+
//# sourceMappingURL=env.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"env.d.ts","sourceRoot":"","sources":["../../src/config/env.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAexB,QAAA,MAAM,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAiJX,CAAC;AAEL,MAAM,MAAM,MAAM,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,SAAS,CAAC,CAAC;AAM/C;;;;;;;;GAQG;AACH,wBAAgB,SAAS,IAAI,MAAM,CAclC;AAED;;;GAGG;AACH,wBAAgB,WAAW,IAAI,IAAI,CAElC;AAED;;GAEG;AACH,wBAAgB,4BAA4B,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAEnE"}
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
import dotenv from 'dotenv';
|
|
2
|
+
import { z } from 'zod';
|
|
3
|
+
import { ConfigError } from '../errors/index.js';
|
|
4
|
+
dotenv.config({ quiet: true });
|
|
5
|
+
// ─── Sensitive Fields (must be non-empty in production) ───
|
|
6
|
+
const PRODUCTION_REQUIRED_PASSWORDS = [
|
|
7
|
+
'NEO4J_PASSWORD',
|
|
8
|
+
'TIMESCALE_PASSWORD',
|
|
9
|
+
'REDIS_PASSWORD',
|
|
10
|
+
];
|
|
11
|
+
// ─── Environment Schema ───
|
|
12
|
+
const envSchema = z
|
|
13
|
+
.object({
|
|
14
|
+
// Runtime
|
|
15
|
+
NODE_ENV: z
|
|
16
|
+
.enum(['development', 'production', 'test'])
|
|
17
|
+
.default('development'),
|
|
18
|
+
LOG_LEVEL: z
|
|
19
|
+
.enum(['trace', 'debug', 'info', 'warn', 'error', 'fatal'])
|
|
20
|
+
.default('info'),
|
|
21
|
+
// Neo4j
|
|
22
|
+
NEO4J_URI: z.string().default('bolt://localhost:7687'),
|
|
23
|
+
NEO4J_USER: z.string().default('neo4j'),
|
|
24
|
+
NEO4J_PASSWORD: z.string().default('tradingboy'),
|
|
25
|
+
// TimescaleDB (individual fields for explicit control)
|
|
26
|
+
TIMESCALE_HOST: z.string().default('localhost'),
|
|
27
|
+
TIMESCALE_PORT: z.coerce.number().int().positive().default(5432),
|
|
28
|
+
TIMESCALE_USER: z.string().default('tradingboy'),
|
|
29
|
+
TIMESCALE_PASSWORD: z.string().default('tradingboy'),
|
|
30
|
+
TIMESCALE_DB: z.string().default('tradingboy'),
|
|
31
|
+
// Redis
|
|
32
|
+
REDIS_URL: z.string().default('redis://localhost:6379'),
|
|
33
|
+
REDIS_PASSWORD: z.string().default('tradingboy_redis_dev'),
|
|
34
|
+
// Data Sources (optional — empty string means not configured)
|
|
35
|
+
JUPITER_API_KEY: z.string().default(''),
|
|
36
|
+
HELIUS_API_KEY: z.string().default(''),
|
|
37
|
+
COINGECKO_API_KEY: z.string().default(''),
|
|
38
|
+
// Future data sources (not yet integrated)
|
|
39
|
+
ALCHEMY_API_KEY: z.string().default(''),
|
|
40
|
+
GLASSNODE_API_KEY: z.string().default(''),
|
|
41
|
+
TWITTER_BEARER_TOKEN: z.string().default(''),
|
|
42
|
+
// AI (legacy — use LLM_API_KEY instead)
|
|
43
|
+
ANTHROPIC_API_KEY: z.string().default(''),
|
|
44
|
+
// LLM Abstraction
|
|
45
|
+
LLM_PROVIDER: z.enum(['anthropic', 'openrouter', 'ollama', 'custom']).default('anthropic'),
|
|
46
|
+
LLM_API_KEY: z.string().default(''),
|
|
47
|
+
LLM_BASE_URL: z.string().default(''),
|
|
48
|
+
LLM_MODEL: z.string().default('claude-sonnet-4-6'),
|
|
49
|
+
LLM_FALLBACK_PROVIDER: z.string().default(''),
|
|
50
|
+
LLM_FALLBACK_MODEL: z.string().default(''),
|
|
51
|
+
LLM_FALLBACK_API_KEY: z.string().default(''),
|
|
52
|
+
LLM_MAX_RETRIES: z.coerce.number().default(2),
|
|
53
|
+
LLM_TIMEOUT_MS: z.coerce.number().default(30000),
|
|
54
|
+
// Learning system
|
|
55
|
+
BELIEF_HMAC_KEY: z.string().default(''),
|
|
56
|
+
// Feature flags
|
|
57
|
+
ENABLE_LLM: z
|
|
58
|
+
.enum(['true', 'false'])
|
|
59
|
+
.default('false')
|
|
60
|
+
.transform((v) => v === 'true'),
|
|
61
|
+
ENABLE_LEARNING: z
|
|
62
|
+
.enum(['true', 'false'])
|
|
63
|
+
.default('false')
|
|
64
|
+
.transform((v) => v === 'true'),
|
|
65
|
+
ENABLE_SOCIAL: z
|
|
66
|
+
.enum(['true', 'false'])
|
|
67
|
+
.default('false')
|
|
68
|
+
.transform((v) => v === 'true'),
|
|
69
|
+
// API
|
|
70
|
+
API_PORT: z.coerce.number().int().positive().default(3000),
|
|
71
|
+
// Telegram Bot
|
|
72
|
+
TELEGRAM_BOT_TOKEN: z.string().default(''),
|
|
73
|
+
TELEGRAM_ALLOWED_CHAT_IDS: z.string().default(''),
|
|
74
|
+
// Email (Resend)
|
|
75
|
+
RESEND_API_KEY: z.string().default(''),
|
|
76
|
+
EMAIL_FROM_ADDRESS: z.string().default('digest@tradingboy.dev'),
|
|
77
|
+
EMAIL_FROM_NAME: z.string().default('Trading Boy'),
|
|
78
|
+
// SMTP (Gateway email adapter)
|
|
79
|
+
SMTP_HOST: z.string().default(''),
|
|
80
|
+
SMTP_PORT: z.coerce.number().int().default(587),
|
|
81
|
+
SMTP_USER: z.string().default(''),
|
|
82
|
+
SMTP_PASS: z.string().default(''),
|
|
83
|
+
NOTIFICATION_FROM_EMAIL: z.string().default('alerts@tradingboy.dev'),
|
|
84
|
+
// Stripe Billing
|
|
85
|
+
STRIPE_SECRET_KEY: z.string().default(''),
|
|
86
|
+
STRIPE_WEBHOOK_SECRET: z.string().default(''),
|
|
87
|
+
STRIPE_PRICE_ID: z.string().default(''),
|
|
88
|
+
APP_URL: z.string().default('http://localhost:3003'),
|
|
89
|
+
// API Authentication
|
|
90
|
+
API_KEY_HASHES: z.string().default(''),
|
|
91
|
+
API_KEY_AUTH_ENABLED: z
|
|
92
|
+
.enum(['true', 'false'])
|
|
93
|
+
.default('true')
|
|
94
|
+
.transform((v) => v === 'true'),
|
|
95
|
+
})
|
|
96
|
+
.superRefine((data, ctx) => {
|
|
97
|
+
if (data.NODE_ENV === 'production') {
|
|
98
|
+
const DEV_DEFAULTS = ['tradingboy', 'tradingboy_redis_dev'];
|
|
99
|
+
for (const field of PRODUCTION_REQUIRED_PASSWORDS) {
|
|
100
|
+
const value = data[field];
|
|
101
|
+
if (!value || DEV_DEFAULTS.includes(value)) {
|
|
102
|
+
ctx.addIssue({
|
|
103
|
+
code: z.ZodIssueCode.custom,
|
|
104
|
+
message: `${field} is required in production mode (cannot be empty or use default value)`,
|
|
105
|
+
path: [field],
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
if (!data.BELIEF_HMAC_KEY) {
|
|
110
|
+
ctx.addIssue({
|
|
111
|
+
code: z.ZodIssueCode.custom,
|
|
112
|
+
message: 'BELIEF_HMAC_KEY is required in production mode for belief state integrity',
|
|
113
|
+
path: ['BELIEF_HMAC_KEY'],
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
// Stripe: if secret key is configured, webhook secret must also be set
|
|
117
|
+
if (data.STRIPE_SECRET_KEY && !data.STRIPE_WEBHOOK_SECRET) {
|
|
118
|
+
ctx.addIssue({
|
|
119
|
+
code: z.ZodIssueCode.custom,
|
|
120
|
+
message: 'STRIPE_WEBHOOK_SECRET is required when STRIPE_SECRET_KEY is configured',
|
|
121
|
+
path: ['STRIPE_WEBHOOK_SECRET'],
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
if (data.STRIPE_SECRET_KEY && !data.STRIPE_PRICE_ID) {
|
|
125
|
+
ctx.addIssue({
|
|
126
|
+
code: z.ZodIssueCode.custom,
|
|
127
|
+
message: 'STRIPE_PRICE_ID is required when STRIPE_SECRET_KEY is configured',
|
|
128
|
+
path: ['STRIPE_PRICE_ID'],
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
// Telegram: if bot token is set, chat IDs must be configured (prevent open-access bot)
|
|
132
|
+
if (data.TELEGRAM_BOT_TOKEN && !data.TELEGRAM_ALLOWED_CHAT_IDS) {
|
|
133
|
+
ctx.addIssue({
|
|
134
|
+
code: z.ZodIssueCode.custom,
|
|
135
|
+
message: 'TELEGRAM_ALLOWED_CHAT_IDS is required in production when TELEGRAM_BOT_TOKEN is set (prevents unauthorized access)',
|
|
136
|
+
path: ['TELEGRAM_ALLOWED_CHAT_IDS'],
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
});
|
|
141
|
+
// ─── Singleton ───
|
|
142
|
+
let _config = null;
|
|
143
|
+
/**
|
|
144
|
+
* Parse and validate environment variables. Returns a cached Config singleton.
|
|
145
|
+
*
|
|
146
|
+
* In production mode, NEO4J_PASSWORD, TIMESCALE_PASSWORD, and REDIS_PASSWORD
|
|
147
|
+
* must be explicitly set to non-default values. In development/test mode,
|
|
148
|
+
* defaults are used so the system works out of the box.
|
|
149
|
+
*
|
|
150
|
+
* @throws {ConfigError} if validation fails
|
|
151
|
+
*/
|
|
152
|
+
export function getConfig() {
|
|
153
|
+
if (!_config) {
|
|
154
|
+
const result = envSchema.safeParse(process.env);
|
|
155
|
+
if (!result.success) {
|
|
156
|
+
const messages = result.error.issues
|
|
157
|
+
.map((issue) => ` - ${issue.path.join('.')}: ${issue.message}`)
|
|
158
|
+
.join('\n');
|
|
159
|
+
throw new ConfigError(`Environment validation failed:\n${messages}`);
|
|
160
|
+
}
|
|
161
|
+
_config = result.data;
|
|
162
|
+
}
|
|
163
|
+
return _config;
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* Reset the config singleton. Used in tests to re-parse environment variables.
|
|
167
|
+
* @internal
|
|
168
|
+
*/
|
|
169
|
+
export function resetConfig() {
|
|
170
|
+
_config = null;
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* Build a PostgreSQL connection string from individual TimescaleDB config fields.
|
|
174
|
+
*/
|
|
175
|
+
export function getTimescaleConnectionString(config) {
|
|
176
|
+
return `postgresql://${config.TIMESCALE_USER}:${config.TIMESCALE_PASSWORD}@${config.TIMESCALE_HOST}:${config.TIMESCALE_PORT}/${config.TIMESCALE_DB}`;
|
|
177
|
+
}
|
|
178
|
+
//# sourceMappingURL=env.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"env.js","sourceRoot":"","sources":["../../src/config/env.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,QAAQ,CAAC;AAC5B,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAEjD,MAAM,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,IAAI,EAAyC,CAAC,CAAC;AAEtE,6DAA6D;AAE7D,MAAM,6BAA6B,GAAG;IACpC,gBAAgB;IAChB,oBAAoB;IACpB,gBAAgB;CACR,CAAC;AAEX,6BAA6B;AAE7B,MAAM,SAAS,GAAG,CAAC;KAChB,MAAM,CAAC;IACN,UAAU;IACV,QAAQ,EAAE,CAAC;SACR,IAAI,CAAC,CAAC,aAAa,EAAE,YAAY,EAAE,MAAM,CAAC,CAAC;SAC3C,OAAO,CAAC,aAAa,CAAC;IACzB,SAAS,EAAE,CAAC;SACT,IAAI,CAAC,CAAC,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;SAC1D,OAAO,CAAC,MAAM,CAAC;IAElB,QAAQ;IACR,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,uBAAuB,CAAC;IACtD,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC;IACvC,cAAc,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,YAAY,CAAC;IAEhD,uDAAuD;IACvD,cAAc,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,WAAW,CAAC;IAC/C,cAAc,EAAE,CAAC,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC;IAChE,cAAc,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,YAAY,CAAC;IAChD,kBAAkB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,YAAY,CAAC;IACpD,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,YAAY,CAAC;IAE9C,QAAQ;IACR,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,wBAAwB,CAAC;IACvD,cAAc,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,sBAAsB,CAAC;IAE1D,8DAA8D;IAC9D,eAAe,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC;IACvC,cAAc,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC;IACtC,iBAAiB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC;IAEzC,2CAA2C;IAC3C,eAAe,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC;IACvC,iBAAiB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC;IACzC,oBAAoB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC;IAE5C,wCAAwC;IACxC,iBAAiB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC;IAEzC,kBAAkB;IAClB,YAAY,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,WAAW,EAAE,YAAY,EAAE,QAAQ,EAAE,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,WAAW,CAAC;IAC1F,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC;IACnC,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC;IACpC,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,mBAAmB,CAAC;IAClD,qBAAqB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC;IAC7C,kBAAkB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC;IAC1C,oBAAoB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC;IAC5C,eAAe,EAAE,CAAC,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC;IAC7C,cAAc,EAAE,CAAC,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC;IAEhD,kBAAkB;IAClB,eAAe,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC;IAEvC,gBAAgB;IAChB,UAAU,EAAE,CAAC;SACV,IAAI,CAAC,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;SACvB,OAAO,CAAC,OAAO,CAAC;SAChB,SAAS,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,MAAM,CAAC;IACjC,eAAe,EAAE,CAAC;SACf,IAAI,CAAC,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;SACvB,OAAO,CAAC,OAAO,CAAC;SAChB,SAAS,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,MAAM,CAAC;IACjC,aAAa,EAAE,CAAC;SACb,IAAI,CAAC,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;SACvB,OAAO,CAAC,OAAO,CAAC;SAChB,SAAS,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,MAAM,CAAC;IAEjC,MAAM;IACN,QAAQ,EAAE,CAAC,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC;IAE1D,eAAe;IACf,kBAAkB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC;IAC1C,yBAAyB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC;IAEjD,iBAAiB;IACjB,cAAc,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC;IACtC,kBAAkB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,uBAAuB,CAAC;IAC/D,eAAe,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,aAAa,CAAC;IAElD,+BAA+B;IAC/B,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC;IACjC,SAAS,EAAE,CAAC,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC;IAC/C,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC;IACjC,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC;IACjC,uBAAuB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,uBAAuB,CAAC;IAEpE,iBAAiB;IACjB,iBAAiB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC;IACzC,qBAAqB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC;IAC7C,eAAe,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC;IACvC,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,uBAAuB,CAAC;IAEpD,qBAAqB;IACrB,cAAc,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC;IACtC,oBAAoB,EAAE,CAAC;SACpB,IAAI,CAAC,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;SACvB,OAAO,CAAC,MAAM,CAAC;SACf,SAAS,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,MAAM,CAAC;CAClC,CAAC;KACD,WAAW,CAAC,CAAC,IAAI,EAAE,GAAG,EAAE,EAAE;IACzB,IAAI,IAAI,CAAC,QAAQ,KAAK,YAAY,EAAE,CAAC;QACnC,MAAM,YAAY,GAAG,CAAC,YAAY,EAAE,sBAAsB,CAAC,CAAC;QAC5D,KAAK,MAAM,KAAK,IAAI,6BAA6B,EAAE,CAAC;YAClD,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC;YAC1B,IAAI,CAAC,KAAK,IAAI,YAAY,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;gBAC3C,GAAG,CAAC,QAAQ,CAAC;oBACX,IAAI,EAAE,CAAC,CAAC,YAAY,CAAC,MAAM;oBAC3B,OAAO,EAAE,GAAG,KAAK,wEAAwE;oBACzF,IAAI,EAAE,CAAC,KAAK,CAAC;iBACd,CAAC,CAAC;YACL,CAAC;QACH,CAAC;QACD,IAAI,CAAC,IAAI,CAAC,eAAe,EAAE,CAAC;YAC1B,GAAG,CAAC,QAAQ,CAAC;gBACX,IAAI,EAAE,CAAC,CAAC,YAAY,CAAC,MAAM;gBAC3B,OAAO,EAAE,2EAA2E;gBACpF,IAAI,EAAE,CAAC,iBAAiB,CAAC;aAC1B,CAAC,CAAC;QACL,CAAC;QAED,uEAAuE;QACvE,IAAI,IAAI,CAAC,iBAAiB,IAAI,CAAC,IAAI,CAAC,qBAAqB,EAAE,CAAC;YAC1D,GAAG,CAAC,QAAQ,CAAC;gBACX,IAAI,EAAE,CAAC,CAAC,YAAY,CAAC,MAAM;gBAC3B,OAAO,EAAE,wEAAwE;gBACjF,IAAI,EAAE,CAAC,uBAAuB,CAAC;aAChC,CAAC,CAAC;QACL,CAAC;QACD,IAAI,IAAI,CAAC,iBAAiB,IAAI,CAAC,IAAI,CAAC,eAAe,EAAE,CAAC;YACpD,GAAG,CAAC,QAAQ,CAAC;gBACX,IAAI,EAAE,CAAC,CAAC,YAAY,CAAC,MAAM;gBAC3B,OAAO,EAAE,kEAAkE;gBAC3E,IAAI,EAAE,CAAC,iBAAiB,CAAC;aAC1B,CAAC,CAAC;QACL,CAAC;QAED,uFAAuF;QACvF,IAAI,IAAI,CAAC,kBAAkB,IAAI,CAAC,IAAI,CAAC,yBAAyB,EAAE,CAAC;YAC/D,GAAG,CAAC,QAAQ,CAAC;gBACX,IAAI,EAAE,CAAC,CAAC,YAAY,CAAC,MAAM;gBAC3B,OAAO,EAAE,mHAAmH;gBAC5H,IAAI,EAAE,CAAC,2BAA2B,CAAC;aACpC,CAAC,CAAC;QACL,CAAC;IACH,CAAC;AACH,CAAC,CAAC,CAAC;AAIL,oBAAoB;AAEpB,IAAI,OAAO,GAAkB,IAAI,CAAC;AAElC;;;;;;;;GAQG;AACH,MAAM,UAAU,SAAS;IACvB,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,MAAM,MAAM,GAAG,SAAS,CAAC,SAAS,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QAChD,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;YACpB,MAAM,QAAQ,GAAG,MAAM,CAAC,KAAK,CAAC,MAAM;iBACjC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,KAAK,CAAC,OAAO,EAAE,CAAC;iBAC/D,IAAI,CAAC,IAAI,CAAC,CAAC;YACd,MAAM,IAAI,WAAW,CACnB,mCAAmC,QAAQ,EAAE,CAC9C,CAAC;QACJ,CAAC;QACD,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC;IACxB,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,WAAW;IACzB,OAAO,GAAG,IAAI,CAAC;AACjB,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,4BAA4B,CAAC,MAAc;IACzD,OAAO,gBAAgB,MAAM,CAAC,cAAc,IAAI,MAAM,CAAC,kBAAkB,IAAI,MAAM,CAAC,cAAc,IAAI,MAAM,CAAC,cAAc,IAAI,MAAM,CAAC,YAAY,EAAE,CAAC;AACvJ,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/config/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,SAAS,EACT,WAAW,EACX,4BAA4B,EAC5B,KAAK,MAAM,GACZ,MAAM,UAAU,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/config/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,SAAS,EACT,WAAW,EACX,4BAA4B,GAE7B,MAAM,UAAU,CAAC"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
export declare const THRESHOLDS: {
|
|
2
|
+
readonly MVRV_OVERVALUED: 3;
|
|
3
|
+
readonly MVRV_UNDERVALUED: 1;
|
|
4
|
+
readonly SOPR_PROFIT_TAKING: 1.05;
|
|
5
|
+
readonly SOPR_CAPITULATION: 0.95;
|
|
6
|
+
readonly FUNDING_HIGH: 0.05;
|
|
7
|
+
readonly FUNDING_NEGATIVE: -0.01;
|
|
8
|
+
readonly OI_SURGE: 20;
|
|
9
|
+
readonly OI_COLLAPSE: -20;
|
|
10
|
+
readonly VOLUME_SPIKE: 3;
|
|
11
|
+
readonly VOLUME_EXTREME: 5;
|
|
12
|
+
readonly WHALE_TX_MIN_USD: 100000;
|
|
13
|
+
readonly UNLOCK_HIGH_PCT: 2;
|
|
14
|
+
readonly UNLOCK_MEDIUM_PCT: 0.5;
|
|
15
|
+
readonly UNLOCK_WEIGHT_TEAM: 1;
|
|
16
|
+
readonly UNLOCK_WEIGHT_VC: 0.8;
|
|
17
|
+
readonly UNLOCK_WEIGHT_ECOSYSTEM: 0.4;
|
|
18
|
+
readonly UNLOCK_WEIGHT_COMMUNITY: 0.3;
|
|
19
|
+
readonly SOCIAL_VELOCITY_SPIKE: 5;
|
|
20
|
+
readonly SENTIMENT_DIVERGENCE: 0.3;
|
|
21
|
+
readonly MINDSHARE_EMERGING: 0.01;
|
|
22
|
+
readonly RISK_SCORE_HIGH: 70;
|
|
23
|
+
readonly RISK_SCORE_CRITICAL: 90;
|
|
24
|
+
readonly TVL_DROP_WARNING: 0.1;
|
|
25
|
+
readonly TVL_DROP_CRITICAL: 0.25;
|
|
26
|
+
};
|
|
27
|
+
export declare const TIME_WINDOWS: {
|
|
28
|
+
readonly TICK: "1m";
|
|
29
|
+
readonly SHORT: "15m";
|
|
30
|
+
readonly MEDIUM: "4h";
|
|
31
|
+
readonly LONG: "1d";
|
|
32
|
+
readonly WEEKLY: "7d";
|
|
33
|
+
readonly MONTHLY: "30d";
|
|
34
|
+
};
|
|
35
|
+
export declare const FRESHNESS_MAX_AGE_MS: {
|
|
36
|
+
readonly MARKET_DATA: number;
|
|
37
|
+
readonly ONCHAIN_DATA: number;
|
|
38
|
+
readonly SOCIAL_DATA: number;
|
|
39
|
+
readonly ANALYTICS_DATA: number;
|
|
40
|
+
readonly EVENT_DATA: number;
|
|
41
|
+
};
|
|
42
|
+
export declare const CONTEXT_DEFAULTS: {
|
|
43
|
+
readonly TRAVERSAL_DEPTH: 2;
|
|
44
|
+
readonly MAX_EVENTS_LOOKAHEAD_DAYS: 30;
|
|
45
|
+
readonly MAX_SOCIAL_LOOKBACK_HOURS: 24;
|
|
46
|
+
readonly MAX_ITEMS_PER_CATEGORY: 10;
|
|
47
|
+
readonly RELEVANCE_CUTOFF: 0.1;
|
|
48
|
+
};
|
|
49
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/constants/index.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,UAAU;;;;;;;;;;;;;;;;;;;;;;;;;CA4Cb,CAAC;AAIX,eAAO,MAAM,YAAY;;;;;;;CAOf,CAAC;AAIX,eAAO,MAAM,oBAAoB;;;;;;CAMvB,CAAC;AAIX,eAAO,MAAM,gBAAgB;;;;;;CAMnB,CAAC"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
// ─── Signal Detection Thresholds ───
|
|
2
|
+
export const THRESHOLDS = {
|
|
3
|
+
// MVRV Z-Score (from on-chain analytics research)
|
|
4
|
+
MVRV_OVERVALUED: 3.0,
|
|
5
|
+
MVRV_UNDERVALUED: 1.0,
|
|
6
|
+
// SOPR (Spent Output Profit Ratio)
|
|
7
|
+
SOPR_PROFIT_TAKING: 1.05,
|
|
8
|
+
SOPR_CAPITULATION: 0.95,
|
|
9
|
+
// Funding rate (8h rate, not annualized — raw exchange data)
|
|
10
|
+
FUNDING_HIGH: 0.05, // 0.05% per 8h = euphoria signal
|
|
11
|
+
FUNDING_NEGATIVE: -0.01,
|
|
12
|
+
// Open interest change (% in 24h)
|
|
13
|
+
OI_SURGE: 20,
|
|
14
|
+
OI_COLLAPSE: -20,
|
|
15
|
+
// Volume anomaly (multiple of 30d average)
|
|
16
|
+
VOLUME_SPIKE: 3.0,
|
|
17
|
+
VOLUME_EXTREME: 5.0,
|
|
18
|
+
// Exchange netflow (positive = inflow = bearish)
|
|
19
|
+
WHALE_TX_MIN_USD: 100_000,
|
|
20
|
+
// Token unlock materiality (% of circulating supply)
|
|
21
|
+
UNLOCK_HIGH_PCT: 2.0,
|
|
22
|
+
UNLOCK_MEDIUM_PCT: 0.5,
|
|
23
|
+
// Unlock recipient weights (from tokenomics research: team unlocks have highest dump probability)
|
|
24
|
+
UNLOCK_WEIGHT_TEAM: 1.0,
|
|
25
|
+
UNLOCK_WEIGHT_VC: 0.8,
|
|
26
|
+
UNLOCK_WEIGHT_ECOSYSTEM: 0.4,
|
|
27
|
+
UNLOCK_WEIGHT_COMMUNITY: 0.3,
|
|
28
|
+
// Social signal thresholds
|
|
29
|
+
SOCIAL_VELOCITY_SPIKE: 5.0, // multiple of 7d average
|
|
30
|
+
SENTIMENT_DIVERGENCE: 0.3,
|
|
31
|
+
MINDSHARE_EMERGING: 0.01, // 1% of total mentions = emerging
|
|
32
|
+
// Risk scoring
|
|
33
|
+
RISK_SCORE_HIGH: 70,
|
|
34
|
+
RISK_SCORE_CRITICAL: 90,
|
|
35
|
+
TVL_DROP_WARNING: 0.1, // 10% drop
|
|
36
|
+
TVL_DROP_CRITICAL: 0.25, // 25% drop
|
|
37
|
+
};
|
|
38
|
+
// ─── Time Windows ───
|
|
39
|
+
export const TIME_WINDOWS = {
|
|
40
|
+
TICK: '1m',
|
|
41
|
+
SHORT: '15m',
|
|
42
|
+
MEDIUM: '4h',
|
|
43
|
+
LONG: '1d',
|
|
44
|
+
WEEKLY: '7d',
|
|
45
|
+
MONTHLY: '30d',
|
|
46
|
+
};
|
|
47
|
+
// ─── Data Freshness Requirements ───
|
|
48
|
+
export const FRESHNESS_MAX_AGE_MS = {
|
|
49
|
+
MARKET_DATA: 5 * 60 * 1000, // 5 minutes
|
|
50
|
+
ONCHAIN_DATA: 15 * 60 * 1000, // ~1 block for EVM
|
|
51
|
+
SOCIAL_DATA: 15 * 60 * 1000, // 15 minutes
|
|
52
|
+
ANALYTICS_DATA: 60 * 60 * 1000, // 1 hour
|
|
53
|
+
EVENT_DATA: 24 * 60 * 60 * 1000, // 1 day
|
|
54
|
+
};
|
|
55
|
+
// ─── Context Assembly ───
|
|
56
|
+
export const CONTEXT_DEFAULTS = {
|
|
57
|
+
TRAVERSAL_DEPTH: 2,
|
|
58
|
+
MAX_EVENTS_LOOKAHEAD_DAYS: 30,
|
|
59
|
+
MAX_SOCIAL_LOOKBACK_HOURS: 24,
|
|
60
|
+
MAX_ITEMS_PER_CATEGORY: 10,
|
|
61
|
+
RELEVANCE_CUTOFF: 0.1,
|
|
62
|
+
};
|
|
63
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/constants/index.ts"],"names":[],"mappings":"AAAA,sCAAsC;AAEtC,MAAM,CAAC,MAAM,UAAU,GAAG;IACxB,kDAAkD;IAClD,eAAe,EAAE,GAAG;IACpB,gBAAgB,EAAE,GAAG;IAErB,mCAAmC;IACnC,kBAAkB,EAAE,IAAI;IACxB,iBAAiB,EAAE,IAAI;IAEvB,6DAA6D;IAC7D,YAAY,EAAE,IAAI,EAAE,iCAAiC;IACrD,gBAAgB,EAAE,CAAC,IAAI;IAEvB,kCAAkC;IAClC,QAAQ,EAAE,EAAE;IACZ,WAAW,EAAE,CAAC,EAAE;IAEhB,2CAA2C;IAC3C,YAAY,EAAE,GAAG;IACjB,cAAc,EAAE,GAAG;IAEnB,iDAAiD;IACjD,gBAAgB,EAAE,OAAO;IAEzB,qDAAqD;IACrD,eAAe,EAAE,GAAG;IACpB,iBAAiB,EAAE,GAAG;IAEtB,kGAAkG;IAClG,kBAAkB,EAAE,GAAG;IACvB,gBAAgB,EAAE,GAAG;IACrB,uBAAuB,EAAE,GAAG;IAC5B,uBAAuB,EAAE,GAAG;IAE5B,2BAA2B;IAC3B,qBAAqB,EAAE,GAAG,EAAE,yBAAyB;IACrD,oBAAoB,EAAE,GAAG;IACzB,kBAAkB,EAAE,IAAI,EAAE,kCAAkC;IAE5D,eAAe;IACf,eAAe,EAAE,EAAE;IACnB,mBAAmB,EAAE,EAAE;IACvB,gBAAgB,EAAE,GAAG,EAAE,WAAW;IAClC,iBAAiB,EAAE,IAAI,EAAE,WAAW;CAC5B,CAAC;AAEX,uBAAuB;AAEvB,MAAM,CAAC,MAAM,YAAY,GAAG;IAC1B,IAAI,EAAE,IAAI;IACV,KAAK,EAAE,KAAK;IACZ,MAAM,EAAE,IAAI;IACZ,IAAI,EAAE,IAAI;IACV,MAAM,EAAE,IAAI;IACZ,OAAO,EAAE,KAAK;CACN,CAAC;AAEX,sCAAsC;AAEtC,MAAM,CAAC,MAAM,oBAAoB,GAAG;IAClC,WAAW,EAAE,CAAC,GAAG,EAAE,GAAG,IAAI,EAAE,YAAY;IACxC,YAAY,EAAE,EAAE,GAAG,EAAE,GAAG,IAAI,EAAE,mBAAmB;IACjD,WAAW,EAAE,EAAE,GAAG,EAAE,GAAG,IAAI,EAAE,aAAa;IAC1C,cAAc,EAAE,EAAE,GAAG,EAAE,GAAG,IAAI,EAAE,SAAS;IACzC,UAAU,EAAE,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,EAAE,QAAQ;CACjC,CAAC;AAEX,2BAA2B;AAE3B,MAAM,CAAC,MAAM,gBAAgB,GAAG;IAC9B,eAAe,EAAE,CAAC;IAClB,yBAAyB,EAAE,EAAE;IAC7B,yBAAyB,EAAE,EAAE;IAC7B,sBAAsB,EAAE,EAAE;IAC1B,gBAAgB,EAAE,GAAG;CACb,CAAC"}
|
package/dist/crypto.d.ts
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/** Fields required for hash computation. Subset of DecisionEvent. */
|
|
2
|
+
interface HashableDecision {
|
|
3
|
+
decisionType: string;
|
|
4
|
+
tokenSymbol: string;
|
|
5
|
+
eventTime: Date;
|
|
6
|
+
direction: string | null;
|
|
7
|
+
entryPrice: number | null;
|
|
8
|
+
exitPrice: number | null;
|
|
9
|
+
size: number | null;
|
|
10
|
+
thesis: string | null;
|
|
11
|
+
confidence: number;
|
|
12
|
+
actor: string;
|
|
13
|
+
}
|
|
14
|
+
/** Result of chain verification. */
|
|
15
|
+
export interface ChainVerificationResult {
|
|
16
|
+
valid: boolean;
|
|
17
|
+
brokenAt?: number;
|
|
18
|
+
}
|
|
19
|
+
/** Minimal shape needed for chain verification. */
|
|
20
|
+
export interface VerifiableDecision extends HashableDecision {
|
|
21
|
+
hash: string;
|
|
22
|
+
previousHash: string | null;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Compute a SHA256 hash for a decision event, chained to the previous hash.
|
|
26
|
+
*
|
|
27
|
+
* The hash is deterministic: same inputs always produce the same hex digest.
|
|
28
|
+
* Fields are serialized in a fixed order to ensure consistency.
|
|
29
|
+
*
|
|
30
|
+
* @param event - Core decision fields to hash
|
|
31
|
+
* @param previousHash - Hash of the preceding decision in the chain, or null for the first
|
|
32
|
+
* @returns Hex-encoded SHA256 hash string
|
|
33
|
+
*/
|
|
34
|
+
export declare function computeDecisionHash(event: HashableDecision, previousHash: string | null): string;
|
|
35
|
+
/**
|
|
36
|
+
* Verify the integrity of a decision hash chain.
|
|
37
|
+
*
|
|
38
|
+
* Iterates through decisions in chronological order, recomputing each hash
|
|
39
|
+
* and checking that it matches the stored hash. The first decision must have
|
|
40
|
+
* `previousHash === null`.
|
|
41
|
+
*
|
|
42
|
+
* @param decisions - Array of decisions in chronological order (oldest first)
|
|
43
|
+
* @returns `{ valid: true }` if the chain is intact, or `{ valid: false, brokenAt: index }`
|
|
44
|
+
*/
|
|
45
|
+
export declare function verifyChain(decisions: VerifiableDecision[]): ChainVerificationResult;
|
|
46
|
+
export {};
|
|
47
|
+
//# sourceMappingURL=crypto.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"crypto.d.ts","sourceRoot":"","sources":["../src/crypto.ts"],"names":[],"mappings":"AAIA,qEAAqE;AACrE,UAAU,gBAAgB;IACxB,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,IAAI,CAAC;IAChB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;CACf;AAED,oCAAoC;AACpC,MAAM,WAAW,uBAAuB;IACtC,KAAK,EAAE,OAAO,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,mDAAmD;AACnD,MAAM,WAAW,kBAAmB,SAAQ,gBAAgB;IAC1D,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;CAC7B;AAID;;;;;;;;;GASG;AACH,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,gBAAgB,EACvB,YAAY,EAAE,MAAM,GAAG,IAAI,GAC1B,MAAM,CAgBR;AAID;;;;;;;;;GASG;AACH,wBAAgB,WAAW,CAAC,SAAS,EAAE,kBAAkB,EAAE,GAAG,uBAAuB,CAkBpF"}
|
package/dist/crypto.js
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { createHash } from 'node:crypto';
|
|
2
|
+
// ─── Hash Computation ───
|
|
3
|
+
/**
|
|
4
|
+
* Compute a SHA256 hash for a decision event, chained to the previous hash.
|
|
5
|
+
*
|
|
6
|
+
* The hash is deterministic: same inputs always produce the same hex digest.
|
|
7
|
+
* Fields are serialized in a fixed order to ensure consistency.
|
|
8
|
+
*
|
|
9
|
+
* @param event - Core decision fields to hash
|
|
10
|
+
* @param previousHash - Hash of the preceding decision in the chain, or null for the first
|
|
11
|
+
* @returns Hex-encoded SHA256 hash string
|
|
12
|
+
*/
|
|
13
|
+
export function computeDecisionHash(event, previousHash) {
|
|
14
|
+
const payload = [
|
|
15
|
+
event.decisionType,
|
|
16
|
+
event.tokenSymbol,
|
|
17
|
+
event.eventTime.toISOString(),
|
|
18
|
+
event.direction ?? '',
|
|
19
|
+
event.entryPrice?.toString() ?? '',
|
|
20
|
+
event.exitPrice?.toString() ?? '',
|
|
21
|
+
event.size?.toString() ?? '',
|
|
22
|
+
event.thesis ?? '',
|
|
23
|
+
event.confidence.toString(),
|
|
24
|
+
event.actor,
|
|
25
|
+
previousHash ?? '',
|
|
26
|
+
].join('|');
|
|
27
|
+
return createHash('sha256').update(payload).digest('hex');
|
|
28
|
+
}
|
|
29
|
+
// ─── Chain Verification ───
|
|
30
|
+
/**
|
|
31
|
+
* Verify the integrity of a decision hash chain.
|
|
32
|
+
*
|
|
33
|
+
* Iterates through decisions in chronological order, recomputing each hash
|
|
34
|
+
* and checking that it matches the stored hash. The first decision must have
|
|
35
|
+
* `previousHash === null`.
|
|
36
|
+
*
|
|
37
|
+
* @param decisions - Array of decisions in chronological order (oldest first)
|
|
38
|
+
* @returns `{ valid: true }` if the chain is intact, or `{ valid: false, brokenAt: index }`
|
|
39
|
+
*/
|
|
40
|
+
export function verifyChain(decisions) {
|
|
41
|
+
for (let i = 0; i < decisions.length; i++) {
|
|
42
|
+
const decision = decisions[i];
|
|
43
|
+
const expectedPreviousHash = i === 0 ? null : decisions[i - 1].hash;
|
|
44
|
+
// Verify previousHash linkage
|
|
45
|
+
if (decision.previousHash !== expectedPreviousHash) {
|
|
46
|
+
return { valid: false, brokenAt: i };
|
|
47
|
+
}
|
|
48
|
+
// Recompute hash and verify
|
|
49
|
+
const recomputed = computeDecisionHash(decision, decision.previousHash);
|
|
50
|
+
if (recomputed !== decision.hash) {
|
|
51
|
+
return { valid: false, brokenAt: i };
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
return { valid: true };
|
|
55
|
+
}
|
|
56
|
+
//# sourceMappingURL=crypto.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"crypto.js","sourceRoot":"","sources":["../src/crypto.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AA8BzC,2BAA2B;AAE3B;;;;;;;;;GASG;AACH,MAAM,UAAU,mBAAmB,CACjC,KAAuB,EACvB,YAA2B;IAE3B,MAAM,OAAO,GAAG;QACd,KAAK,CAAC,YAAY;QAClB,KAAK,CAAC,WAAW;QACjB,KAAK,CAAC,SAAS,CAAC,WAAW,EAAE;QAC7B,KAAK,CAAC,SAAS,IAAI,EAAE;QACrB,KAAK,CAAC,UAAU,EAAE,QAAQ,EAAE,IAAI,EAAE;QAClC,KAAK,CAAC,SAAS,EAAE,QAAQ,EAAE,IAAI,EAAE;QACjC,KAAK,CAAC,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE;QAC5B,KAAK,CAAC,MAAM,IAAI,EAAE;QAClB,KAAK,CAAC,UAAU,CAAC,QAAQ,EAAE;QAC3B,KAAK,CAAC,KAAK;QACX,YAAY,IAAI,EAAE;KACnB,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAEZ,OAAO,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AAC5D,CAAC;AAED,6BAA6B;AAE7B;;;;;;;;;GASG;AACH,MAAM,UAAU,WAAW,CAAC,SAA+B;IACzD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,SAAS,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QAC1C,MAAM,QAAQ,GAAG,SAAS,CAAC,CAAC,CAAC,CAAC;QAC9B,MAAM,oBAAoB,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC;QAEpE,8BAA8B;QAC9B,IAAI,QAAQ,CAAC,YAAY,KAAK,oBAAoB,EAAE,CAAC;YACnD,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,EAAE,CAAC;QACvC,CAAC;QAED,4BAA4B;QAC5B,MAAM,UAAU,GAAG,mBAAmB,CAAC,QAAQ,EAAE,QAAQ,CAAC,YAAY,CAAC,CAAC;QACxE,IAAI,UAAU,KAAK,QAAQ,CAAC,IAAI,EAAE,CAAC;YACjC,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,EAAE,CAAC;QACvC,CAAC;IACH,CAAC;IAED,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;AACzB,CAAC"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
export declare class TradingBoyError extends Error {
|
|
2
|
+
readonly code: string;
|
|
3
|
+
constructor(message: string, code: string);
|
|
4
|
+
}
|
|
5
|
+
export declare class DatabaseError extends TradingBoyError {
|
|
6
|
+
constructor(message: string);
|
|
7
|
+
}
|
|
8
|
+
export declare class NetworkError extends TradingBoyError {
|
|
9
|
+
readonly statusCode: number | undefined;
|
|
10
|
+
readonly url: string;
|
|
11
|
+
constructor(message: string, url: string, statusCode?: number);
|
|
12
|
+
}
|
|
13
|
+
export declare class ValidationError extends TradingBoyError {
|
|
14
|
+
readonly field: string;
|
|
15
|
+
constructor(message: string, field: string);
|
|
16
|
+
}
|
|
17
|
+
export declare class ConfigError extends TradingBoyError {
|
|
18
|
+
constructor(message: string);
|
|
19
|
+
}
|
|
20
|
+
export declare class NotFoundError extends TradingBoyError {
|
|
21
|
+
readonly entity: string;
|
|
22
|
+
readonly id: string;
|
|
23
|
+
constructor(entity: string, id: string);
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/errors/index.ts"],"names":[],"mappings":"AAEA,qBAAa,eAAgB,SAAQ,KAAK;IACxC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;gBAEV,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM;CAK1C;AAID,qBAAa,aAAc,SAAQ,eAAe;gBACpC,OAAO,EAAE,MAAM;CAG5B;AAID,qBAAa,YAAa,SAAQ,eAAe;IAC/C,QAAQ,CAAC,UAAU,EAAE,MAAM,GAAG,SAAS,CAAC;IACxC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;gBAET,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM;CAK9D;AAID,qBAAa,eAAgB,SAAQ,eAAe;IAClD,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;gBAEX,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM;CAI3C;AAID,qBAAa,WAAY,SAAQ,eAAe;gBAClC,OAAO,EAAE,MAAM;CAG5B;AAID,qBAAa,aAAc,SAAQ,eAAe;IAChD,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;gBAER,MAAM,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM;CAKvC"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
// ─── Base Error ───
|
|
2
|
+
export class TradingBoyError extends Error {
|
|
3
|
+
code;
|
|
4
|
+
constructor(message, code) {
|
|
5
|
+
super(message);
|
|
6
|
+
this.name = this.constructor.name;
|
|
7
|
+
this.code = code;
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
// ─── Database ───
|
|
11
|
+
export class DatabaseError extends TradingBoyError {
|
|
12
|
+
constructor(message) {
|
|
13
|
+
super(message, 'DB_ERROR');
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
// ─── Network ───
|
|
17
|
+
export class NetworkError extends TradingBoyError {
|
|
18
|
+
statusCode;
|
|
19
|
+
url;
|
|
20
|
+
constructor(message, url, statusCode) {
|
|
21
|
+
super(message, 'NETWORK_ERROR');
|
|
22
|
+
this.url = url;
|
|
23
|
+
this.statusCode = statusCode;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
// ─── Validation ───
|
|
27
|
+
export class ValidationError extends TradingBoyError {
|
|
28
|
+
field;
|
|
29
|
+
constructor(message, field) {
|
|
30
|
+
super(message, 'VALIDATION_ERROR');
|
|
31
|
+
this.field = field;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
// ─── Config ───
|
|
35
|
+
export class ConfigError extends TradingBoyError {
|
|
36
|
+
constructor(message) {
|
|
37
|
+
super(message, 'CONFIG_ERROR');
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
// ─── Not Found ───
|
|
41
|
+
export class NotFoundError extends TradingBoyError {
|
|
42
|
+
entity;
|
|
43
|
+
id;
|
|
44
|
+
constructor(entity, id) {
|
|
45
|
+
super(`${entity} not found: ${id}`, 'NOT_FOUND');
|
|
46
|
+
this.entity = entity;
|
|
47
|
+
this.id = id;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/errors/index.ts"],"names":[],"mappings":"AAAA,qBAAqB;AAErB,MAAM,OAAO,eAAgB,SAAQ,KAAK;IAC/B,IAAI,CAAS;IAEtB,YAAY,OAAe,EAAE,IAAY;QACvC,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC;QAClC,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;IACnB,CAAC;CACF;AAED,mBAAmB;AAEnB,MAAM,OAAO,aAAc,SAAQ,eAAe;IAChD,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC;IAC7B,CAAC;CACF;AAED,kBAAkB;AAElB,MAAM,OAAO,YAAa,SAAQ,eAAe;IACtC,UAAU,CAAqB;IAC/B,GAAG,CAAS;IAErB,YAAY,OAAe,EAAE,GAAW,EAAE,UAAmB;QAC3D,KAAK,CAAC,OAAO,EAAE,eAAe,CAAC,CAAC;QAChC,IAAI,CAAC,GAAG,GAAG,GAAG,CAAC;QACf,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC;IAC/B,CAAC;CACF;AAED,qBAAqB;AAErB,MAAM,OAAO,eAAgB,SAAQ,eAAe;IACzC,KAAK,CAAS;IAEvB,YAAY,OAAe,EAAE,KAAa;QACxC,KAAK,CAAC,OAAO,EAAE,kBAAkB,CAAC,CAAC;QACnC,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;IACrB,CAAC;CACF;AAED,iBAAiB;AAEjB,MAAM,OAAO,WAAY,SAAQ,eAAe;IAC9C,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,EAAE,cAAc,CAAC,CAAC;IACjC,CAAC;CACF;AAED,oBAAoB;AAEpB,MAAM,OAAO,aAAc,SAAQ,eAAe;IACvC,MAAM,CAAS;IACf,EAAE,CAAS;IAEpB,YAAY,MAAc,EAAE,EAAU;QACpC,KAAK,CAAC,GAAG,MAAM,eAAe,EAAE,EAAE,EAAE,WAAW,CAAC,CAAC;QACjD,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,EAAE,GAAG,EAAE,CAAC;IACf,CAAC;CACF"}
|