@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.
Files changed (79) hide show
  1. package/README.md +8 -0
  2. package/dist/.gitkeep +0 -0
  3. package/dist/config/env.d.ts +102 -0
  4. package/dist/config/env.d.ts.map +1 -0
  5. package/dist/config/env.js +178 -0
  6. package/dist/config/env.js.map +1 -0
  7. package/dist/config/index.d.ts +2 -0
  8. package/dist/config/index.d.ts.map +1 -0
  9. package/dist/config/index.js +2 -0
  10. package/dist/config/index.js.map +1 -0
  11. package/dist/constants/index.d.ts +49 -0
  12. package/dist/constants/index.d.ts.map +1 -0
  13. package/dist/constants/index.js +63 -0
  14. package/dist/constants/index.js.map +1 -0
  15. package/dist/crypto.d.ts +47 -0
  16. package/dist/crypto.d.ts.map +1 -0
  17. package/dist/crypto.js +56 -0
  18. package/dist/crypto.js.map +1 -0
  19. package/dist/errors/index.d.ts +25 -0
  20. package/dist/errors/index.d.ts.map +1 -0
  21. package/dist/errors/index.js +50 -0
  22. package/dist/errors/index.js.map +1 -0
  23. package/dist/index.d.ts +13 -0
  24. package/dist/index.d.ts.map +1 -0
  25. package/dist/index.js +13 -0
  26. package/dist/index.js.map +1 -0
  27. package/dist/llm/client.d.ts +38 -0
  28. package/dist/llm/client.d.ts.map +1 -0
  29. package/dist/llm/client.js +194 -0
  30. package/dist/llm/client.js.map +1 -0
  31. package/dist/llm/config.d.ts +12 -0
  32. package/dist/llm/config.d.ts.map +1 -0
  33. package/dist/llm/config.js +47 -0
  34. package/dist/llm/config.js.map +1 -0
  35. package/dist/llm/index.d.ts +5 -0
  36. package/dist/llm/index.d.ts.map +1 -0
  37. package/dist/llm/index.js +4 -0
  38. package/dist/llm/index.js.map +1 -0
  39. package/dist/llm/structured-output.d.ts +31 -0
  40. package/dist/llm/structured-output.d.ts.map +1 -0
  41. package/dist/llm/structured-output.js +69 -0
  42. package/dist/llm/structured-output.js.map +1 -0
  43. package/dist/llm/types.d.ts +39 -0
  44. package/dist/llm/types.d.ts.map +1 -0
  45. package/dist/llm/types.js +6 -0
  46. package/dist/llm/types.js.map +1 -0
  47. package/dist/logging/index.d.ts +2 -0
  48. package/dist/logging/index.d.ts.map +1 -0
  49. package/dist/logging/index.js +2 -0
  50. package/dist/logging/index.js.map +1 -0
  51. package/dist/logging/logger.d.ts +7 -0
  52. package/dist/logging/logger.d.ts.map +1 -0
  53. package/dist/logging/logger.js +66 -0
  54. package/dist/logging/logger.js.map +1 -0
  55. package/dist/types/context-package.d.ts +100 -0
  56. package/dist/types/context-package.d.ts.map +1 -0
  57. package/dist/types/context-package.js +2 -0
  58. package/dist/types/context-package.js.map +1 -0
  59. package/dist/types/daily-summary.d.ts +212 -0
  60. package/dist/types/daily-summary.d.ts.map +1 -0
  61. package/dist/types/daily-summary.js +6 -0
  62. package/dist/types/daily-summary.js.map +1 -0
  63. package/dist/types/decision-traces.d.ts +123 -0
  64. package/dist/types/decision-traces.d.ts.map +1 -0
  65. package/dist/types/decision-traces.js +2 -0
  66. package/dist/types/decision-traces.js.map +1 -0
  67. package/dist/types/enums.d.ts +207 -0
  68. package/dist/types/enums.d.ts.map +1 -0
  69. package/dist/types/enums.js +247 -0
  70. package/dist/types/enums.js.map +1 -0
  71. package/dist/types/graph-edges.d.ts +127 -0
  72. package/dist/types/graph-edges.d.ts.map +1 -0
  73. package/dist/types/graph-edges.js +3 -0
  74. package/dist/types/graph-edges.js.map +1 -0
  75. package/dist/types/graph-nodes.d.ts +79 -0
  76. package/dist/types/graph-nodes.d.ts.map +1 -0
  77. package/dist/types/graph-nodes.js +2 -0
  78. package/dist/types/graph-nodes.js.map +1 -0
  79. package/package.json +31 -0
package/README.md ADDED
@@ -0,0 +1,8 @@
1
+ # @trading-boy/core
2
+
3
+ Shared types, constants, and utilities for the Trading Boy monorepo.
4
+
5
+ ## Contents
6
+
7
+ - **types/** — Graph node types, edge types, ContextPackage interface, enums
8
+ - **constants/** — Threshold values, configuration constants
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":"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"}
@@ -0,0 +1,2 @@
1
+ export { getConfig, resetConfig, getTimescaleConnectionString, type Config, } from './env.js';
2
+ //# sourceMappingURL=index.d.ts.map
@@ -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,2 @@
1
+ export { getConfig, resetConfig, getTimescaleConnectionString, } from './env.js';
2
+ //# sourceMappingURL=index.js.map
@@ -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"}
@@ -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"}