@elizaos/plugin-social-alpha 2.0.3-beta.5 → 2.0.3-beta.7
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/dist/clients.d.ts +354 -0
- package/dist/clients.d.ts.map +1 -0
- package/dist/clients.js +670 -0
- package/dist/clients.js.map +1 -0
- package/dist/config.d.ts +144 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +122 -0
- package/dist/config.js.map +1 -0
- package/dist/events.d.ts +5 -0
- package/dist/events.d.ts.map +1 -0
- package/dist/events.js +426 -0
- package/dist/events.js.map +1 -0
- package/dist/frontend/LeaderboardView.helpers.d.ts +6 -0
- package/dist/frontend/LeaderboardView.helpers.d.ts.map +1 -0
- package/dist/frontend/LeaderboardView.helpers.js +59 -0
- package/dist/frontend/LeaderboardView.helpers.js.map +1 -0
- package/dist/frontend/SocialAlphaSpatialView.d.ts +52 -0
- package/dist/frontend/SocialAlphaSpatialView.d.ts.map +1 -0
- package/dist/frontend/SocialAlphaSpatialView.js +72 -0
- package/dist/frontend/SocialAlphaSpatialView.js.map +1 -0
- package/dist/frontend/SocialAlphaView.d.ts +35 -0
- package/dist/frontend/SocialAlphaView.d.ts.map +1 -0
- package/dist/frontend/SocialAlphaView.js +125 -0
- package/dist/frontend/SocialAlphaView.js.map +1 -0
- package/dist/index.d.ts +24 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +73 -0
- package/dist/index.js.map +1 -0
- package/dist/mockPriceService.d.ts +22 -0
- package/dist/mockPriceService.d.ts.map +1 -0
- package/dist/mockPriceService.js +21 -0
- package/dist/mockPriceService.js.map +1 -0
- package/dist/providers/socialAlphaProvider.d.ts +15 -0
- package/dist/providers/socialAlphaProvider.d.ts.map +1 -0
- package/dist/providers/socialAlphaProvider.js +261 -0
- package/dist/providers/socialAlphaProvider.js.map +1 -0
- package/dist/register-terminal-view.d.ts +15 -0
- package/dist/register-terminal-view.d.ts.map +1 -0
- package/dist/register-terminal-view.js +21 -0
- package/dist/register-terminal-view.js.map +1 -0
- package/dist/register.d.ts +10 -0
- package/dist/register.d.ts.map +1 -0
- package/dist/register.js +5 -0
- package/dist/register.js.map +1 -0
- package/dist/reports.d.ts +57 -0
- package/dist/reports.d.ts.map +1 -0
- package/dist/reports.js +455 -0
- package/dist/reports.js.map +1 -0
- package/dist/routes.d.ts +3 -0
- package/dist/routes.d.ts.map +1 -0
- package/dist/routes.js +59 -0
- package/dist/routes.js.map +1 -0
- package/dist/schemas.d.ts +151 -0
- package/dist/schemas.d.ts.map +1 -0
- package/dist/schemas.js +258 -0
- package/dist/schemas.js.map +1 -0
- package/dist/service.d.ts +306 -0
- package/dist/service.d.ts.map +1 -0
- package/dist/service.js +3078 -0
- package/dist/service.js.map +1 -0
- package/dist/services/balancedTrustScoreCalculator.d.ts +61 -0
- package/dist/services/balancedTrustScoreCalculator.d.ts.map +1 -0
- package/dist/services/balancedTrustScoreCalculator.js +207 -0
- package/dist/services/balancedTrustScoreCalculator.js.map +1 -0
- package/dist/services/historicalPriceService.d.ts +59 -0
- package/dist/services/historicalPriceService.d.ts.map +1 -0
- package/dist/services/historicalPriceService.js +291 -0
- package/dist/services/historicalPriceService.js.map +1 -0
- package/dist/services/index.d.ts +12 -0
- package/dist/services/index.d.ts.map +1 -0
- package/dist/services/index.js +17 -0
- package/dist/services/index.js.map +1 -0
- package/dist/services/priceEnrichmentService.d.ts +109 -0
- package/dist/services/priceEnrichmentService.d.ts.map +1 -0
- package/dist/services/priceEnrichmentService.js +780 -0
- package/dist/services/priceEnrichmentService.js.map +1 -0
- package/dist/services/simulationActorsV2.d.ts +54 -0
- package/dist/services/simulationActorsV2.d.ts.map +1 -0
- package/dist/services/simulationActorsV2.js +362 -0
- package/dist/services/simulationActorsV2.js.map +1 -0
- package/dist/services/simulationRunner.d.ts +113 -0
- package/dist/services/simulationRunner.d.ts.map +1 -0
- package/dist/services/simulationRunner.js +771 -0
- package/dist/services/simulationRunner.js.map +1 -0
- package/dist/services/tokenSimulationService.d.ts +34 -0
- package/dist/services/tokenSimulationService.d.ts.map +1 -0
- package/dist/services/tokenSimulationService.js +297 -0
- package/dist/services/tokenSimulationService.js.map +1 -0
- package/dist/services/trustScoreOptimizer.d.ts +110 -0
- package/dist/services/trustScoreOptimizer.d.ts.map +1 -0
- package/dist/services/trustScoreOptimizer.js +635 -0
- package/dist/services/trustScoreOptimizer.js.map +1 -0
- package/dist/simulationActors.d.ts +35 -0
- package/dist/simulationActors.d.ts.map +1 -0
- package/dist/simulationActors.js +160 -0
- package/dist/simulationActors.js.map +1 -0
- package/dist/social-alpha-view-bundle.d.ts +2 -0
- package/dist/social-alpha-view-bundle.d.ts.map +1 -0
- package/dist/social-alpha-view-bundle.js +5 -0
- package/dist/social-alpha-view-bundle.js.map +1 -0
- package/dist/types.d.ts +937 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +46 -0
- package/dist/types.js.map +1 -0
- package/dist/views/brand/background/clouds_background.jpg +0 -0
- package/dist/views/brand/banners/eliza_banner.svg +20 -0
- package/dist/views/brand/banners/elizacloud_banner.svg +20 -0
- package/dist/views/brand/banners/elizaos_banner.svg +20 -0
- package/dist/views/brand/concepts/billboard_concept_1200.jpg +0 -0
- package/dist/views/brand/concepts/chibi_usb_concept_900.jpg +0 -0
- package/dist/views/brand/concepts/concept_minipc_900.jpg +0 -0
- package/dist/views/brand/concepts/concept_phone_800.jpg +0 -0
- package/dist/views/brand/concepts/concept_usbdrive_900.jpg +0 -0
- package/dist/views/brand/favicons/android-chrome-192x192.png +0 -0
- package/dist/views/brand/favicons/android-chrome-512x512.png +0 -0
- package/dist/views/brand/favicons/apple-touch-icon.png +0 -0
- package/dist/views/brand/favicons/favicon-16x16.png +0 -0
- package/dist/views/brand/favicons/favicon-32x32.png +0 -0
- package/dist/views/brand/favicons/favicon.ico +0 -0
- package/dist/views/brand/favicons/favicon.svg +17 -0
- package/dist/views/brand/logos/elizaOS_text_black.svg +3 -0
- package/dist/views/brand/logos/elizaOS_text_white.svg +3 -0
- package/dist/views/brand/logos/eliza_logotext.svg +26 -0
- package/dist/views/brand/logos/eliza_logotext_black.svg +26 -0
- package/dist/views/brand/logos/eliza_text_black.svg +3 -0
- package/dist/views/brand/logos/eliza_text_white.svg +3 -0
- package/dist/views/brand/logos/elizacloud_logotext.svg +26 -0
- package/dist/views/brand/logos/elizacloud_logotext_black.svg +26 -0
- package/dist/views/brand/logos/elizacloud_text_black.svg +3 -0
- package/dist/views/brand/logos/elizacloud_text_white.svg +3 -0
- package/dist/views/brand/logos/elizaos_logotext.svg +26 -0
- package/dist/views/brand/logos/elizaos_logotext_black.svg +26 -0
- package/dist/views/brand/logos/logo_blue_blackbg.svg +18 -0
- package/dist/views/brand/logos/logo_blue_nobg.svg +17 -0
- package/dist/views/brand/logos/logo_orange_blackbg.svg +18 -0
- package/dist/views/brand/logos/logo_orange_nobg.svg +17 -0
- package/dist/views/brand/logos/logo_white_blackbg.svg +25 -0
- package/dist/views/brand/logos/logo_white_bluebg.svg +25 -0
- package/dist/views/brand/logos/logo_white_graybg.svg +18 -0
- package/dist/views/brand/logos/logo_white_nobg.svg +24 -0
- package/dist/views/brand/logos/logo_white_orangebg.svg +25 -0
- package/dist/views/brand/ogembeds/eliza_ogembed.png +0 -0
- package/dist/views/brand/ogembeds/eliza_ogembed.svg +20 -0
- package/dist/views/brand/ogembeds/elizacloud_ogembed.png +0 -0
- package/dist/views/brand/ogembeds/elizacloud_ogembed.svg +20 -0
- package/dist/views/brand/ogembeds/elizaos_ogembed.png +0 -0
- package/dist/views/brand/ogembeds/elizaos_ogembed.svg +20 -0
- package/dist/views/bundle.js +268 -0
- package/dist/views/bundle.js.map +1 -0
- package/dist/views/site.webmanifest +19 -0
- package/package.json +5 -5
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
class BalancedTrustScoreCalculator {
|
|
2
|
+
params = {
|
|
3
|
+
profitWeight: 0.25,
|
|
4
|
+
winRateWeight: 0.25,
|
|
5
|
+
sharpeWeight: 0.15,
|
|
6
|
+
alphaWeight: 0.1,
|
|
7
|
+
consistencyWeight: 0.1,
|
|
8
|
+
qualityWeight: 0.15,
|
|
9
|
+
normalVolumeThreshold: 100,
|
|
10
|
+
highVolumeThreshold: 300,
|
|
11
|
+
extremeVolumeThreshold: 500,
|
|
12
|
+
volumeToleranceByArchetype: {
|
|
13
|
+
elite_analyst: 2,
|
|
14
|
+
// Can make 2x more calls
|
|
15
|
+
skilled_trader: 1.5,
|
|
16
|
+
technical_analyst: 1.3,
|
|
17
|
+
contrarian: 1,
|
|
18
|
+
newbie: 0.8,
|
|
19
|
+
fomo_trader: 0.6,
|
|
20
|
+
pump_chaser: 0.5,
|
|
21
|
+
bot_spammer: 0.3,
|
|
22
|
+
// Much lower tolerance
|
|
23
|
+
rug_promoter: 0.3
|
|
24
|
+
}
|
|
25
|
+
};
|
|
26
|
+
/**
|
|
27
|
+
* Calculate balanced trust score
|
|
28
|
+
*/
|
|
29
|
+
calculateBalancedTrustScore(metrics, archetype, rugPromotions, goodCalls, totalCalls) {
|
|
30
|
+
const archetypeBase = this.getArchetypeBase(archetype);
|
|
31
|
+
const components = {
|
|
32
|
+
profit: this.calculateProfitComponent(metrics.averageProfit) * this.params.profitWeight,
|
|
33
|
+
winRate: this.calculateWinRateComponent(metrics.winRate) * this.params.winRateWeight,
|
|
34
|
+
sharpe: this.calculateSharpeComponent(metrics.sharpeRatio) * this.params.sharpeWeight,
|
|
35
|
+
alpha: this.calculateAlphaComponent(metrics.alpha) * this.params.alphaWeight,
|
|
36
|
+
consistency: metrics.consistency * 100 * this.params.consistencyWeight,
|
|
37
|
+
quality: this.calculateQualityComponent(rugPromotions, goodCalls, totalCalls) * this.params.qualityWeight
|
|
38
|
+
};
|
|
39
|
+
const performanceScore = Object.values(components).reduce(
|
|
40
|
+
(sum, val) => sum + val,
|
|
41
|
+
0
|
|
42
|
+
);
|
|
43
|
+
const scalingFactor = this.getArchetypeScaling(archetype);
|
|
44
|
+
const scaledPerformance = performanceScore * scalingFactor;
|
|
45
|
+
const volumeAdjustment = this.calculateVolumeAdjustment(
|
|
46
|
+
totalCalls,
|
|
47
|
+
archetype
|
|
48
|
+
);
|
|
49
|
+
let finalScore = archetypeBase * 0.4 + scaledPerformance * 0.6;
|
|
50
|
+
finalScore *= volumeAdjustment;
|
|
51
|
+
if (totalCalls < 5) {
|
|
52
|
+
finalScore *= 0.8;
|
|
53
|
+
} else if (totalCalls < 10) {
|
|
54
|
+
finalScore *= 0.9;
|
|
55
|
+
}
|
|
56
|
+
return Math.min(100, Math.max(0, finalScore));
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Archetype base scores with good spread
|
|
60
|
+
*/
|
|
61
|
+
getArchetypeBase(archetype) {
|
|
62
|
+
const bases = {
|
|
63
|
+
elite_analyst: 85,
|
|
64
|
+
skilled_trader: 65,
|
|
65
|
+
technical_analyst: 55,
|
|
66
|
+
contrarian: 50,
|
|
67
|
+
newbie: 35,
|
|
68
|
+
fomo_trader: 25,
|
|
69
|
+
pump_chaser: 20,
|
|
70
|
+
bot_spammer: 10,
|
|
71
|
+
rug_promoter: 5
|
|
72
|
+
};
|
|
73
|
+
return bases[archetype] || 30;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Profit component with better scaling
|
|
77
|
+
*/
|
|
78
|
+
calculateProfitComponent(avgProfit) {
|
|
79
|
+
if (avgProfit > 50) {
|
|
80
|
+
return 90 + Math.min(10, (avgProfit - 50) * 0.1);
|
|
81
|
+
} else if (avgProfit > 20) {
|
|
82
|
+
return 70 + (avgProfit - 20) * 0.67;
|
|
83
|
+
} else if (avgProfit > 0) {
|
|
84
|
+
return 50 + avgProfit;
|
|
85
|
+
} else if (avgProfit > -30) {
|
|
86
|
+
return 30 + avgProfit / 30 * 20;
|
|
87
|
+
} else {
|
|
88
|
+
return Math.max(0, 30 + avgProfit * 0.3);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Win rate component with smooth curve
|
|
93
|
+
*/
|
|
94
|
+
calculateWinRateComponent(winRate) {
|
|
95
|
+
if (winRate >= 0.8) {
|
|
96
|
+
return 85 + (winRate - 0.8) * 75;
|
|
97
|
+
} else if (winRate >= 0.6) {
|
|
98
|
+
return 70 + (winRate - 0.6) * 75;
|
|
99
|
+
} else if (winRate >= 0.5) {
|
|
100
|
+
return 50 + (winRate - 0.5) * 200;
|
|
101
|
+
} else if (winRate >= 0.3) {
|
|
102
|
+
return 20 + (winRate - 0.3) * 150;
|
|
103
|
+
} else {
|
|
104
|
+
return winRate * 66.67;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Sharpe ratio component
|
|
109
|
+
*/
|
|
110
|
+
calculateSharpeComponent(sharpe) {
|
|
111
|
+
if (sharpe > 1.5) {
|
|
112
|
+
return 90 + Math.min(10, (sharpe - 1.5) * 10);
|
|
113
|
+
} else if (sharpe > 0.5) {
|
|
114
|
+
return 60 + (sharpe - 0.5) * 30;
|
|
115
|
+
} else if (sharpe > 0) {
|
|
116
|
+
return 50 + sharpe * 20;
|
|
117
|
+
} else if (sharpe > -1) {
|
|
118
|
+
return 30 + sharpe * 20;
|
|
119
|
+
} else {
|
|
120
|
+
return Math.max(0, 30 + sharpe * 10);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Alpha component - fixed to handle negative values better
|
|
125
|
+
*/
|
|
126
|
+
calculateAlphaComponent(alpha) {
|
|
127
|
+
if (alpha > 20) {
|
|
128
|
+
return 80 + Math.min(20, (alpha - 20) * 0.5);
|
|
129
|
+
} else if (alpha > 0) {
|
|
130
|
+
return 50 + alpha * 1.5;
|
|
131
|
+
} else if (alpha > -20) {
|
|
132
|
+
return 50 + alpha * 1.5;
|
|
133
|
+
} else {
|
|
134
|
+
return Math.max(0, 50 + alpha * 0.5);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Quality component based on call quality
|
|
139
|
+
*/
|
|
140
|
+
calculateQualityComponent(rugPromotions, goodCalls, totalCalls) {
|
|
141
|
+
if (totalCalls === 0) return 50;
|
|
142
|
+
const goodRatio = goodCalls / totalCalls;
|
|
143
|
+
const rugRatio = rugPromotions / totalCalls;
|
|
144
|
+
let quality = goodRatio * 100;
|
|
145
|
+
quality -= rugRatio * 200;
|
|
146
|
+
if (goodRatio > 0.5) {
|
|
147
|
+
quality += 20;
|
|
148
|
+
}
|
|
149
|
+
return Math.max(0, Math.min(100, quality));
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Volume adjustment - multiplicative factor instead of penalty
|
|
153
|
+
*/
|
|
154
|
+
calculateVolumeAdjustment(totalCalls, archetype) {
|
|
155
|
+
const tolerance = this.params.volumeToleranceByArchetype[archetype] || 1;
|
|
156
|
+
const adjustedThresholds = {
|
|
157
|
+
normal: this.params.normalVolumeThreshold * tolerance,
|
|
158
|
+
high: this.params.highVolumeThreshold * tolerance,
|
|
159
|
+
extreme: this.params.extremeVolumeThreshold * tolerance
|
|
160
|
+
};
|
|
161
|
+
if (totalCalls <= adjustedThresholds.normal) {
|
|
162
|
+
return 1;
|
|
163
|
+
} else if (totalCalls <= adjustedThresholds.high) {
|
|
164
|
+
const ratio = (totalCalls - adjustedThresholds.normal) / (adjustedThresholds.high - adjustedThresholds.normal);
|
|
165
|
+
return 1 - ratio * 0.2;
|
|
166
|
+
} else if (totalCalls <= adjustedThresholds.extreme) {
|
|
167
|
+
const ratio = (totalCalls - adjustedThresholds.high) / (adjustedThresholds.extreme - adjustedThresholds.high);
|
|
168
|
+
return 0.8 - ratio * 0.3;
|
|
169
|
+
} else {
|
|
170
|
+
return 0.5;
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* Archetype performance scaling
|
|
175
|
+
*/
|
|
176
|
+
getArchetypeScaling(archetype) {
|
|
177
|
+
const scaling = {
|
|
178
|
+
elite_analyst: 1.15,
|
|
179
|
+
// Slight boost
|
|
180
|
+
skilled_trader: 1.1,
|
|
181
|
+
technical_analyst: 1.05,
|
|
182
|
+
contrarian: 1,
|
|
183
|
+
newbie: 0.95,
|
|
184
|
+
fomo_trader: 0.85,
|
|
185
|
+
pump_chaser: 0.75,
|
|
186
|
+
bot_spammer: 0.6,
|
|
187
|
+
rug_promoter: 0.5
|
|
188
|
+
};
|
|
189
|
+
return scaling[archetype] || 0.9;
|
|
190
|
+
}
|
|
191
|
+
/**
|
|
192
|
+
* Set custom parameters
|
|
193
|
+
*/
|
|
194
|
+
setParameters(params) {
|
|
195
|
+
this.params = { ...this.params, ...params };
|
|
196
|
+
}
|
|
197
|
+
/**
|
|
198
|
+
* Get current parameters
|
|
199
|
+
*/
|
|
200
|
+
getParameters() {
|
|
201
|
+
return { ...this.params };
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
export {
|
|
205
|
+
BalancedTrustScoreCalculator
|
|
206
|
+
};
|
|
207
|
+
//# sourceMappingURL=balancedTrustScoreCalculator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/services/balancedTrustScoreCalculator.ts"],"sourcesContent":["import type { TrustScoreResult } from \"./trustScoreOptimizer.js\";\n\nexport interface BalancedTrustScoreParams {\n\t// Base weights\n\tprofitWeight: number;\n\twinRateWeight: number;\n\tsharpeWeight: number;\n\talphaWeight: number;\n\tconsistencyWeight: number;\n\tqualityWeight: number;\n\n\t// Volume thresholds - more nuanced\n\tnormalVolumeThreshold: number; // Below this = normal\n\thighVolumeThreshold: number; // Above this = potential spam\n\textremeVolumeThreshold: number; // Definite spam\n\n\t// Archetype-specific volume multipliers\n\tvolumeToleranceByArchetype: Record<string, number>;\n}\n\nexport class BalancedTrustScoreCalculator {\n\tprivate params: BalancedTrustScoreParams = {\n\t\tprofitWeight: 0.25,\n\t\twinRateWeight: 0.25,\n\t\tsharpeWeight: 0.15,\n\t\talphaWeight: 0.1,\n\t\tconsistencyWeight: 0.1,\n\t\tqualityWeight: 0.15,\n\t\tnormalVolumeThreshold: 100,\n\t\thighVolumeThreshold: 300,\n\t\textremeVolumeThreshold: 500,\n\t\tvolumeToleranceByArchetype: {\n\t\t\telite_analyst: 2.0, // Can make 2x more calls\n\t\t\tskilled_trader: 1.5,\n\t\t\ttechnical_analyst: 1.3,\n\t\t\tcontrarian: 1.0,\n\t\t\tnewbie: 0.8,\n\t\t\tfomo_trader: 0.6,\n\t\t\tpump_chaser: 0.5,\n\t\t\tbot_spammer: 0.3, // Much lower tolerance\n\t\t\trug_promoter: 0.3,\n\t\t},\n\t};\n\n\t/**\n\t * Calculate balanced trust score\n\t */\n\tcalculateBalancedTrustScore(\n\t\tmetrics: TrustScoreResult[\"metrics\"],\n\t\tarchetype: string,\n\t\trugPromotions: number,\n\t\tgoodCalls: number,\n\t\ttotalCalls: number,\n\t): number {\n\t\t// 1. Base score from archetype (30% weight)\n\t\tconst archetypeBase = this.getArchetypeBase(archetype);\n\n\t\t// 2. Performance components\n\t\tconst components = {\n\t\t\tprofit:\n\t\t\t\tthis.calculateProfitComponent(metrics.averageProfit) *\n\t\t\t\tthis.params.profitWeight,\n\t\t\twinRate:\n\t\t\t\tthis.calculateWinRateComponent(metrics.winRate) *\n\t\t\t\tthis.params.winRateWeight,\n\t\t\tsharpe:\n\t\t\t\tthis.calculateSharpeComponent(metrics.sharpeRatio) *\n\t\t\t\tthis.params.sharpeWeight,\n\t\t\talpha:\n\t\t\t\tthis.calculateAlphaComponent(metrics.alpha) * this.params.alphaWeight,\n\t\t\tconsistency: metrics.consistency * 100 * this.params.consistencyWeight,\n\t\t\tquality:\n\t\t\t\tthis.calculateQualityComponent(rugPromotions, goodCalls, totalCalls) *\n\t\t\t\tthis.params.qualityWeight,\n\t\t};\n\n\t\t// 3. Sum performance score\n\t\tconst performanceScore = Object.values(components).reduce(\n\t\t\t(sum, val) => sum + val,\n\t\t\t0,\n\t\t);\n\n\t\t// 4. Apply archetype scaling\n\t\tconst scalingFactor = this.getArchetypeScaling(archetype);\n\t\tconst scaledPerformance = performanceScore * scalingFactor;\n\n\t\t// 5. Volume adjustment (not penalty)\n\t\tconst volumeAdjustment = this.calculateVolumeAdjustment(\n\t\t\ttotalCalls,\n\t\t\tarchetype,\n\t\t);\n\n\t\t// 6. Combine components\n\t\tlet finalScore = archetypeBase * 0.4 + scaledPerformance * 0.6;\n\t\tfinalScore *= volumeAdjustment; // Multiplicative adjustment instead of subtractive penalty\n\n\t\t// 7. Data sufficiency adjustment\n\t\tif (totalCalls < 5) {\n\t\t\tfinalScore *= 0.8; // 20% reduction for insufficient data\n\t\t} else if (totalCalls < 10) {\n\t\t\tfinalScore *= 0.9; // 10% reduction\n\t\t}\n\n\t\t// 8. Bounds check\n\t\treturn Math.min(100, Math.max(0, finalScore));\n\t}\n\n\t/**\n\t * Archetype base scores with good spread\n\t */\n\tprivate getArchetypeBase(archetype: string): number {\n\t\tconst bases: Record<string, number> = {\n\t\t\telite_analyst: 85,\n\t\t\tskilled_trader: 65,\n\t\t\ttechnical_analyst: 55,\n\t\t\tcontrarian: 50,\n\t\t\tnewbie: 35,\n\t\t\tfomo_trader: 25,\n\t\t\tpump_chaser: 20,\n\t\t\tbot_spammer: 10,\n\t\t\trug_promoter: 5,\n\t\t};\n\t\treturn bases[archetype] || 30;\n\t}\n\n\t/**\n\t * Profit component with better scaling\n\t */\n\tprivate calculateProfitComponent(avgProfit: number): number {\n\t\tif (avgProfit > 50) {\n\t\t\treturn 90 + Math.min(10, (avgProfit - 50) * 0.1);\n\t\t} else if (avgProfit > 20) {\n\t\t\treturn 70 + (avgProfit - 20) * 0.67;\n\t\t} else if (avgProfit > 0) {\n\t\t\treturn 50 + avgProfit;\n\t\t} else if (avgProfit > -30) {\n\t\t\treturn 30 + (avgProfit / 30) * 20;\n\t\t} else {\n\t\t\treturn Math.max(0, 30 + avgProfit * 0.3);\n\t\t}\n\t}\n\n\t/**\n\t * Win rate component with smooth curve\n\t */\n\tprivate calculateWinRateComponent(winRate: number): number {\n\t\t// Sigmoid-like curve\n\t\tif (winRate >= 0.8) {\n\t\t\treturn 85 + (winRate - 0.8) * 75;\n\t\t} else if (winRate >= 0.6) {\n\t\t\treturn 70 + (winRate - 0.6) * 75;\n\t\t} else if (winRate >= 0.5) {\n\t\t\treturn 50 + (winRate - 0.5) * 200;\n\t\t} else if (winRate >= 0.3) {\n\t\t\treturn 20 + (winRate - 0.3) * 150;\n\t\t} else {\n\t\t\treturn winRate * 66.67;\n\t\t}\n\t}\n\n\t/**\n\t * Sharpe ratio component\n\t */\n\tprivate calculateSharpeComponent(sharpe: number): number {\n\t\tif (sharpe > 1.5) {\n\t\t\treturn 90 + Math.min(10, (sharpe - 1.5) * 10);\n\t\t} else if (sharpe > 0.5) {\n\t\t\treturn 60 + (sharpe - 0.5) * 30;\n\t\t} else if (sharpe > 0) {\n\t\t\treturn 50 + sharpe * 20;\n\t\t} else if (sharpe > -1) {\n\t\t\treturn 30 + sharpe * 20;\n\t\t} else {\n\t\t\treturn Math.max(0, 30 + sharpe * 10);\n\t\t}\n\t}\n\n\t/**\n\t * Alpha component - fixed to handle negative values better\n\t */\n\tprivate calculateAlphaComponent(alpha: number): number {\n\t\t// Note: Alpha can be negative if underperforming market\n\t\t// We'll normalize around 0 being neutral (50 score)\n\t\tif (alpha > 20) {\n\t\t\treturn 80 + Math.min(20, (alpha - 20) * 0.5);\n\t\t} else if (alpha > 0) {\n\t\t\treturn 50 + alpha * 1.5;\n\t\t} else if (alpha > -20) {\n\t\t\treturn 50 + alpha * 1.5; // Same slope for fairness\n\t\t} else {\n\t\t\treturn Math.max(0, 50 + alpha * 0.5);\n\t\t}\n\t}\n\n\t/**\n\t * Quality component based on call quality\n\t */\n\tprivate calculateQualityComponent(\n\t\trugPromotions: number,\n\t\tgoodCalls: number,\n\t\ttotalCalls: number,\n\t): number {\n\t\tif (totalCalls === 0) return 50;\n\n\t\t// Good call ratio\n\t\tconst goodRatio = goodCalls / totalCalls;\n\t\t// Rug promotion ratio\n\t\tconst rugRatio = rugPromotions / totalCalls;\n\n\t\t// Base quality from good calls\n\t\tlet quality = goodRatio * 100;\n\n\t\t// Heavy penalty for rug promotions\n\t\tquality -= rugRatio * 200; // Double penalty\n\n\t\t// Bonus for high good call ratio\n\t\tif (goodRatio > 0.5) {\n\t\t\tquality += 20;\n\t\t}\n\n\t\treturn Math.max(0, Math.min(100, quality));\n\t}\n\n\t/**\n\t * Volume adjustment - multiplicative factor instead of penalty\n\t */\n\tprivate calculateVolumeAdjustment(\n\t\ttotalCalls: number,\n\t\tarchetype: string,\n\t): number {\n\t\tconst tolerance = this.params.volumeToleranceByArchetype[archetype] || 1.0;\n\t\tconst adjustedThresholds = {\n\t\t\tnormal: this.params.normalVolumeThreshold * tolerance,\n\t\t\thigh: this.params.highVolumeThreshold * tolerance,\n\t\t\textreme: this.params.extremeVolumeThreshold * tolerance,\n\t\t};\n\n\t\tif (totalCalls <= adjustedThresholds.normal) {\n\t\t\treturn 1.0; // No adjustment\n\t\t} else if (totalCalls <= adjustedThresholds.high) {\n\t\t\t// Gradual reduction from 1.0 to 0.8\n\t\t\tconst ratio =\n\t\t\t\t(totalCalls - adjustedThresholds.normal) /\n\t\t\t\t(adjustedThresholds.high - adjustedThresholds.normal);\n\t\t\treturn 1.0 - ratio * 0.2;\n\t\t} else if (totalCalls <= adjustedThresholds.extreme) {\n\t\t\t// Steeper reduction from 0.8 to 0.5\n\t\t\tconst ratio =\n\t\t\t\t(totalCalls - adjustedThresholds.high) /\n\t\t\t\t(adjustedThresholds.extreme - adjustedThresholds.high);\n\t\t\treturn 0.8 - ratio * 0.3;\n\t\t} else {\n\t\t\t// Extreme volume\n\t\t\treturn 0.5; // 50% reduction max\n\t\t}\n\t}\n\n\t/**\n\t * Archetype performance scaling\n\t */\n\tprivate getArchetypeScaling(archetype: string): number {\n\t\tconst scaling: Record<string, number> = {\n\t\t\telite_analyst: 1.15, // Slight boost\n\t\t\tskilled_trader: 1.1,\n\t\t\ttechnical_analyst: 1.05,\n\t\t\tcontrarian: 1.0,\n\t\t\tnewbie: 0.95,\n\t\t\tfomo_trader: 0.85,\n\t\t\tpump_chaser: 0.75,\n\t\t\tbot_spammer: 0.6,\n\t\t\trug_promoter: 0.5,\n\t\t};\n\t\treturn scaling[archetype] || 0.9;\n\t}\n\n\t/**\n\t * Set custom parameters\n\t */\n\tsetParameters(params: Partial<BalancedTrustScoreParams>): void {\n\t\tthis.params = { ...this.params, ...params };\n\t}\n\n\t/**\n\t * Get current parameters\n\t */\n\tgetParameters(): BalancedTrustScoreParams {\n\t\treturn { ...this.params };\n\t}\n}\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import type { IAgentRuntime } from "@elizaos/core";
|
|
2
|
+
import { SupportedChain } from "../types.ts";
|
|
3
|
+
export interface PricePoint {
|
|
4
|
+
timestamp: number;
|
|
5
|
+
price: number;
|
|
6
|
+
volume?: number;
|
|
7
|
+
liquidity?: number;
|
|
8
|
+
}
|
|
9
|
+
export interface HistoricalPriceData {
|
|
10
|
+
address: string;
|
|
11
|
+
chain: SupportedChain;
|
|
12
|
+
priceHistory: PricePoint[];
|
|
13
|
+
firstPrice?: number;
|
|
14
|
+
lastPrice?: number;
|
|
15
|
+
minPrice?: number;
|
|
16
|
+
maxPrice?: number;
|
|
17
|
+
fetchedAt: number;
|
|
18
|
+
}
|
|
19
|
+
export interface TokenResolution {
|
|
20
|
+
symbol: string;
|
|
21
|
+
address: string;
|
|
22
|
+
name: string;
|
|
23
|
+
chain: SupportedChain;
|
|
24
|
+
liquidity?: number;
|
|
25
|
+
volume24h?: number;
|
|
26
|
+
marketCap?: number;
|
|
27
|
+
createdAt?: number;
|
|
28
|
+
}
|
|
29
|
+
export declare class HistoricalPriceService {
|
|
30
|
+
private birdeyeClient;
|
|
31
|
+
private dexscreenerClient;
|
|
32
|
+
constructor(runtime: IAgentRuntime);
|
|
33
|
+
/**
|
|
34
|
+
* Fetch historical price data from Birdeye using OHLCV endpoint
|
|
35
|
+
*/
|
|
36
|
+
fetchBirdeyeHistoricalPrices(address: string, fromTimestamp: number, toTimestamp: number): Promise<HistoricalPriceData | null>;
|
|
37
|
+
/**
|
|
38
|
+
* Fetch historical price data from Dexscreener
|
|
39
|
+
* Note: DexScreener doesn't provide true historical data, only recent price changes
|
|
40
|
+
*/
|
|
41
|
+
fetchDexscreenerHistoricalPrices(address: string, chain: SupportedChain, _fromTimestamp: number, _toTimestamp: number): Promise<HistoricalPriceData | null>;
|
|
42
|
+
/**
|
|
43
|
+
* Get price at specific timestamp using interpolation
|
|
44
|
+
*/
|
|
45
|
+
getPriceAtTimestamp(historicalData: HistoricalPriceData, timestamp: number): number | null;
|
|
46
|
+
/**
|
|
47
|
+
* Get max price in time window
|
|
48
|
+
*/
|
|
49
|
+
getMaxPriceInWindow(historicalData: HistoricalPriceData, fromTimestamp: number, toTimestamp: number): {
|
|
50
|
+
price: number;
|
|
51
|
+
timestamp: number;
|
|
52
|
+
} | null;
|
|
53
|
+
/**
|
|
54
|
+
* Search for best token match by symbol
|
|
55
|
+
*/
|
|
56
|
+
findBestTokenMatch(symbol: string, chain: SupportedChain): Promise<TokenResolution | null>;
|
|
57
|
+
private getChainId;
|
|
58
|
+
}
|
|
59
|
+
//# sourceMappingURL=historicalPriceService.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"historicalPriceService.d.ts","sourceRoot":"","sources":["../../src/services/historicalPriceService.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAEnD,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAE7C,MAAM,WAAW,UAAU;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,mBAAmB;IACnC,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,cAAc,CAAC;IACtB,YAAY,EAAE,UAAU,EAAE,CAAC;IAC3B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,eAAe;IAC/B,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,cAAc,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,qBAAa,sBAAsB;IAClC,OAAO,CAAC,aAAa,CAAgB;IACrC,OAAO,CAAC,iBAAiB,CAAoB;gBAEjC,OAAO,EAAE,aAAa;IAKlC;;OAEG;IACG,4BAA4B,CACjC,OAAO,EAAE,MAAM,EACf,aAAa,EAAE,MAAM,EACrB,WAAW,EAAE,MAAM,GACjB,OAAO,CAAC,mBAAmB,GAAG,IAAI,CAAC;IA0GtC;;;OAGG;IACG,gCAAgC,CACrC,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,cAAc,EACrB,cAAc,EAAE,MAAM,EACtB,YAAY,EAAE,MAAM,GAClB,OAAO,CAAC,mBAAmB,GAAG,IAAI,CAAC;IA8FtC;;OAEG;IACH,mBAAmB,CAClB,cAAc,EAAE,mBAAmB,EACnC,SAAS,EAAE,MAAM,GACf,MAAM,GAAG,IAAI;IAmChB;;OAEG;IACH,mBAAmB,CAClB,cAAc,EAAE,mBAAmB,EACnC,aAAa,EAAE,MAAM,EACrB,WAAW,EAAE,MAAM,GACjB;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI;IAgC9C;;OAEG;IACG,kBAAkB,CACvB,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,cAAc,GACnB,OAAO,CAAC,eAAe,GAAG,IAAI,CAAC;IAsElC,OAAO,CAAC,UAAU;CAYlB"}
|
|
@@ -0,0 +1,291 @@
|
|
|
1
|
+
import { BirdeyeClient, DexscreenerClient } from "../clients.js";
|
|
2
|
+
import { SupportedChain } from "../types.js";
|
|
3
|
+
class HistoricalPriceService {
|
|
4
|
+
birdeyeClient;
|
|
5
|
+
dexscreenerClient;
|
|
6
|
+
constructor(runtime) {
|
|
7
|
+
this.birdeyeClient = BirdeyeClient.createFromRuntime(runtime);
|
|
8
|
+
this.dexscreenerClient = DexscreenerClient.createFromRuntime(runtime);
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Fetch historical price data from Birdeye using OHLCV endpoint
|
|
12
|
+
*/
|
|
13
|
+
async fetchBirdeyeHistoricalPrices(address, fromTimestamp, toTimestamp) {
|
|
14
|
+
try {
|
|
15
|
+
const fromSec = Math.floor(fromTimestamp / 1e3);
|
|
16
|
+
const toSec = Math.floor(toTimestamp / 1e3);
|
|
17
|
+
const ohlcvData = await this.birdeyeClient.request(
|
|
18
|
+
"defi/ohlcv",
|
|
19
|
+
{
|
|
20
|
+
address,
|
|
21
|
+
type: "1H",
|
|
22
|
+
// 1 hour intervals
|
|
23
|
+
time_from: fromSec,
|
|
24
|
+
time_to: toSec
|
|
25
|
+
},
|
|
26
|
+
{ chain: "solana" }
|
|
27
|
+
);
|
|
28
|
+
if (!ohlcvData?.items || ohlcvData.items.length === 0) {
|
|
29
|
+
const currentPrice = await this.birdeyeClient.fetchPrice(address);
|
|
30
|
+
if (currentPrice) {
|
|
31
|
+
return {
|
|
32
|
+
address,
|
|
33
|
+
chain: SupportedChain.SOLANA,
|
|
34
|
+
priceHistory: [
|
|
35
|
+
{
|
|
36
|
+
timestamp: Date.now(),
|
|
37
|
+
price: currentPrice
|
|
38
|
+
}
|
|
39
|
+
],
|
|
40
|
+
firstPrice: currentPrice,
|
|
41
|
+
lastPrice: currentPrice,
|
|
42
|
+
minPrice: currentPrice,
|
|
43
|
+
maxPrice: currentPrice,
|
|
44
|
+
fetchedAt: Date.now()
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
return null;
|
|
48
|
+
}
|
|
49
|
+
const priceHistory = ohlcvData.items.map((item) => ({
|
|
50
|
+
timestamp: item.unixTime * 1e3,
|
|
51
|
+
price: item.c,
|
|
52
|
+
// Use closing price
|
|
53
|
+
volume: item.v
|
|
54
|
+
}));
|
|
55
|
+
const prices = priceHistory.map((p) => p.price);
|
|
56
|
+
return {
|
|
57
|
+
address,
|
|
58
|
+
chain: SupportedChain.SOLANA,
|
|
59
|
+
priceHistory,
|
|
60
|
+
firstPrice: prices[0],
|
|
61
|
+
lastPrice: prices[prices.length - 1],
|
|
62
|
+
minPrice: Math.min(...prices),
|
|
63
|
+
maxPrice: Math.max(...prices),
|
|
64
|
+
fetchedAt: Date.now()
|
|
65
|
+
};
|
|
66
|
+
} catch (error) {
|
|
67
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
68
|
+
console.warn(
|
|
69
|
+
`OHLCV failed for ${address}, trying current price:`,
|
|
70
|
+
message
|
|
71
|
+
);
|
|
72
|
+
try {
|
|
73
|
+
const currentPrice = await this.birdeyeClient.fetchPrice(address);
|
|
74
|
+
if (currentPrice) {
|
|
75
|
+
return {
|
|
76
|
+
address,
|
|
77
|
+
chain: SupportedChain.SOLANA,
|
|
78
|
+
priceHistory: [
|
|
79
|
+
{
|
|
80
|
+
timestamp: Date.now(),
|
|
81
|
+
price: currentPrice
|
|
82
|
+
}
|
|
83
|
+
],
|
|
84
|
+
firstPrice: currentPrice,
|
|
85
|
+
lastPrice: currentPrice,
|
|
86
|
+
minPrice: currentPrice,
|
|
87
|
+
maxPrice: currentPrice,
|
|
88
|
+
fetchedAt: Date.now()
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
} catch (priceError) {
|
|
92
|
+
console.error(
|
|
93
|
+
`Failed to get any price data for ${address}:`,
|
|
94
|
+
priceError
|
|
95
|
+
);
|
|
96
|
+
}
|
|
97
|
+
return null;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Fetch historical price data from Dexscreener
|
|
102
|
+
* Note: DexScreener doesn't provide true historical data, only recent price changes
|
|
103
|
+
*/
|
|
104
|
+
async fetchDexscreenerHistoricalPrices(address, chain, _fromTimestamp, _toTimestamp) {
|
|
105
|
+
try {
|
|
106
|
+
const searchResults = await this.dexscreenerClient.search(address);
|
|
107
|
+
if (!searchResults?.pairs || searchResults.pairs.length === 0) {
|
|
108
|
+
return null;
|
|
109
|
+
}
|
|
110
|
+
const chainId = this.getChainId(chain);
|
|
111
|
+
const pair = searchResults.pairs.find(
|
|
112
|
+
(p) => p.baseToken.address.toLowerCase() === address.toLowerCase() && p.chainId === chainId
|
|
113
|
+
) || searchResults.pairs[0];
|
|
114
|
+
if (!pair?.priceUsd) {
|
|
115
|
+
return null;
|
|
116
|
+
}
|
|
117
|
+
const priceHistory = [];
|
|
118
|
+
const currentPrice = parseFloat(pair.priceUsd);
|
|
119
|
+
const now = Date.now();
|
|
120
|
+
priceHistory.push({
|
|
121
|
+
timestamp: now,
|
|
122
|
+
price: currentPrice,
|
|
123
|
+
volume: pair.volume?.h24,
|
|
124
|
+
liquidity: pair.liquidity?.usd
|
|
125
|
+
});
|
|
126
|
+
if (pair.priceChange) {
|
|
127
|
+
if (pair.priceChange.m5 !== void 0) {
|
|
128
|
+
const price5m = currentPrice / (1 + pair.priceChange.m5 / 100);
|
|
129
|
+
priceHistory.push({
|
|
130
|
+
timestamp: now - 5 * 60 * 1e3,
|
|
131
|
+
price: price5m
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
if (pair.priceChange.h1 !== void 0) {
|
|
135
|
+
const price1h = currentPrice / (1 + pair.priceChange.h1 / 100);
|
|
136
|
+
priceHistory.push({
|
|
137
|
+
timestamp: now - 60 * 60 * 1e3,
|
|
138
|
+
price: price1h
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
if (pair.priceChange.h6 !== void 0) {
|
|
142
|
+
const price6h = currentPrice / (1 + pair.priceChange.h6 / 100);
|
|
143
|
+
priceHistory.push({
|
|
144
|
+
timestamp: now - 6 * 60 * 60 * 1e3,
|
|
145
|
+
price: price6h
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
if (pair.priceChange.h24 !== void 0) {
|
|
149
|
+
const price24h = currentPrice / (1 + pair.priceChange.h24 / 100);
|
|
150
|
+
priceHistory.push({
|
|
151
|
+
timestamp: now - 24 * 60 * 60 * 1e3,
|
|
152
|
+
price: price24h
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
priceHistory.sort((a, b) => a.timestamp - b.timestamp);
|
|
157
|
+
const prices = priceHistory.map((p) => p.price);
|
|
158
|
+
return {
|
|
159
|
+
address,
|
|
160
|
+
chain,
|
|
161
|
+
priceHistory,
|
|
162
|
+
firstPrice: prices[0],
|
|
163
|
+
lastPrice: prices[prices.length - 1],
|
|
164
|
+
minPrice: Math.min(...prices),
|
|
165
|
+
maxPrice: Math.max(...prices),
|
|
166
|
+
fetchedAt: Date.now()
|
|
167
|
+
};
|
|
168
|
+
} catch (error) {
|
|
169
|
+
console.error(`Error fetching Dexscreener data for ${address}:`, error);
|
|
170
|
+
return null;
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* Get price at specific timestamp using interpolation
|
|
175
|
+
*/
|
|
176
|
+
getPriceAtTimestamp(historicalData, timestamp) {
|
|
177
|
+
const priceHistory = historicalData.priceHistory;
|
|
178
|
+
if (priceHistory.length === 0) return null;
|
|
179
|
+
if (timestamp <= priceHistory[0].timestamp) {
|
|
180
|
+
return priceHistory[0].price;
|
|
181
|
+
}
|
|
182
|
+
if (timestamp >= priceHistory[priceHistory.length - 1].timestamp) {
|
|
183
|
+
return priceHistory[priceHistory.length - 1].price;
|
|
184
|
+
}
|
|
185
|
+
for (let i = 0; i < priceHistory.length - 1; i++) {
|
|
186
|
+
if (timestamp >= priceHistory[i].timestamp && timestamp <= priceHistory[i + 1].timestamp) {
|
|
187
|
+
const t1 = priceHistory[i].timestamp;
|
|
188
|
+
const t2 = priceHistory[i + 1].timestamp;
|
|
189
|
+
const p1 = priceHistory[i].price;
|
|
190
|
+
const p2 = priceHistory[i + 1].price;
|
|
191
|
+
const ratio = (timestamp - t1) / (t2 - t1);
|
|
192
|
+
return p1 + (p2 - p1) * ratio;
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
return null;
|
|
196
|
+
}
|
|
197
|
+
/**
|
|
198
|
+
* Get max price in time window
|
|
199
|
+
*/
|
|
200
|
+
getMaxPriceInWindow(historicalData, fromTimestamp, toTimestamp) {
|
|
201
|
+
const pricesInWindow = historicalData.priceHistory.filter(
|
|
202
|
+
(p) => p.timestamp >= fromTimestamp && p.timestamp <= toTimestamp
|
|
203
|
+
);
|
|
204
|
+
if (pricesInWindow.length === 0) {
|
|
205
|
+
const priceAtStart = this.getPriceAtTimestamp(
|
|
206
|
+
historicalData,
|
|
207
|
+
fromTimestamp
|
|
208
|
+
);
|
|
209
|
+
const priceAtEnd = this.getPriceAtTimestamp(historicalData, toTimestamp);
|
|
210
|
+
if (priceAtStart !== null && priceAtEnd !== null) {
|
|
211
|
+
return priceAtStart >= priceAtEnd ? { price: priceAtStart, timestamp: fromTimestamp } : { price: priceAtEnd, timestamp: toTimestamp };
|
|
212
|
+
}
|
|
213
|
+
return null;
|
|
214
|
+
}
|
|
215
|
+
let maxPrice = pricesInWindow[0];
|
|
216
|
+
for (const point of pricesInWindow) {
|
|
217
|
+
if (point.price > maxPrice.price) {
|
|
218
|
+
maxPrice = point;
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
return { price: maxPrice.price, timestamp: maxPrice.timestamp };
|
|
222
|
+
}
|
|
223
|
+
/**
|
|
224
|
+
* Search for best token match by symbol
|
|
225
|
+
*/
|
|
226
|
+
async findBestTokenMatch(symbol, chain) {
|
|
227
|
+
try {
|
|
228
|
+
const searchResults = await this.dexscreenerClient.search(symbol);
|
|
229
|
+
if (!searchResults?.pairs || searchResults.pairs.length === 0) {
|
|
230
|
+
return null;
|
|
231
|
+
}
|
|
232
|
+
const chainId = this.getChainId(chain);
|
|
233
|
+
const candidates = searchResults.pairs.filter(
|
|
234
|
+
(pair) => pair.chainId === chainId && pair.baseToken.symbol.toUpperCase() === symbol.toUpperCase()
|
|
235
|
+
).sort((a, b) => {
|
|
236
|
+
const liquidityA = a.liquidity?.usd || 0;
|
|
237
|
+
const liquidityB = b.liquidity?.usd || 0;
|
|
238
|
+
if (liquidityA !== liquidityB) {
|
|
239
|
+
return liquidityB - liquidityA;
|
|
240
|
+
}
|
|
241
|
+
const volumeA = a.volume?.h24 || 0;
|
|
242
|
+
const volumeB = b.volume?.h24 || 0;
|
|
243
|
+
if (volumeA !== volumeB) {
|
|
244
|
+
return volumeB - volumeA;
|
|
245
|
+
}
|
|
246
|
+
return (b.pairCreatedAt || 0) - (a.pairCreatedAt || 0);
|
|
247
|
+
});
|
|
248
|
+
if (candidates.length === 0) {
|
|
249
|
+
return null;
|
|
250
|
+
}
|
|
251
|
+
const bestMatch = candidates[0];
|
|
252
|
+
const liquidityUsd = bestMatch.liquidity?.usd || 0;
|
|
253
|
+
const marketCap = bestMatch.fdv || 0;
|
|
254
|
+
const minLiquidityRatio = 1e4 / 1e6;
|
|
255
|
+
if (marketCap > 0 && liquidityUsd / marketCap < minLiquidityRatio) {
|
|
256
|
+
console.warn(
|
|
257
|
+
`Token ${symbol} has insufficient liquidity ratio: ${liquidityUsd / marketCap}`
|
|
258
|
+
);
|
|
259
|
+
}
|
|
260
|
+
return {
|
|
261
|
+
symbol: bestMatch.baseToken.symbol,
|
|
262
|
+
address: bestMatch.baseToken.address,
|
|
263
|
+
name: bestMatch.baseToken.name,
|
|
264
|
+
chain,
|
|
265
|
+
liquidity: liquidityUsd,
|
|
266
|
+
volume24h: bestMatch.volume?.h24,
|
|
267
|
+
marketCap: bestMatch.fdv,
|
|
268
|
+
createdAt: bestMatch.pairCreatedAt
|
|
269
|
+
};
|
|
270
|
+
} catch (error) {
|
|
271
|
+
console.error(`Error finding best token match for ${symbol}:`, error);
|
|
272
|
+
return null;
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
getChainId(chain) {
|
|
276
|
+
switch (chain) {
|
|
277
|
+
case SupportedChain.SOLANA:
|
|
278
|
+
return "solana";
|
|
279
|
+
case SupportedChain.ETHEREUM:
|
|
280
|
+
return "ethereum";
|
|
281
|
+
case SupportedChain.BASE:
|
|
282
|
+
return "base";
|
|
283
|
+
default:
|
|
284
|
+
return "solana";
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
export {
|
|
289
|
+
HistoricalPriceService
|
|
290
|
+
};
|
|
291
|
+
//# sourceMappingURL=historicalPriceService.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/services/historicalPriceService.ts"],"sourcesContent":["import type { IAgentRuntime } from \"@elizaos/core\";\nimport { BirdeyeClient, DexscreenerClient } from \"../clients.js\";\nimport { SupportedChain } from \"../types.js\";\n\nexport interface PricePoint {\n\ttimestamp: number;\n\tprice: number;\n\tvolume?: number;\n\tliquidity?: number;\n}\n\nexport interface HistoricalPriceData {\n\taddress: string;\n\tchain: SupportedChain;\n\tpriceHistory: PricePoint[];\n\tfirstPrice?: number;\n\tlastPrice?: number;\n\tminPrice?: number;\n\tmaxPrice?: number;\n\tfetchedAt: number;\n}\n\nexport interface TokenResolution {\n\tsymbol: string;\n\taddress: string;\n\tname: string;\n\tchain: SupportedChain;\n\tliquidity?: number;\n\tvolume24h?: number;\n\tmarketCap?: number;\n\tcreatedAt?: number;\n}\n\nexport class HistoricalPriceService {\n\tprivate birdeyeClient: BirdeyeClient;\n\tprivate dexscreenerClient: DexscreenerClient;\n\n\tconstructor(runtime: IAgentRuntime) {\n\t\tthis.birdeyeClient = BirdeyeClient.createFromRuntime(runtime);\n\t\tthis.dexscreenerClient = DexscreenerClient.createFromRuntime(runtime);\n\t}\n\n\t/**\n\t * Fetch historical price data from Birdeye using OHLCV endpoint\n\t */\n\tasync fetchBirdeyeHistoricalPrices(\n\t\taddress: string,\n\t\tfromTimestamp: number,\n\t\ttoTimestamp: number,\n\t): Promise<HistoricalPriceData | null> {\n\t\ttry {\n\t\t\t// Convert timestamps to seconds (Birdeye expects seconds)\n\t\t\tconst fromSec = Math.floor(fromTimestamp / 1000);\n\t\t\tconst toSec = Math.floor(toTimestamp / 1000);\n\n\t\t\t// Try OHLCV endpoint\n\t\t\tconst ohlcvData = await this.birdeyeClient.request<{\n\t\t\t\titems: Array<{\n\t\t\t\t\tunixTime: number;\n\t\t\t\t\to: number; // open\n\t\t\t\t\th: number; // high\n\t\t\t\t\tl: number; // low\n\t\t\t\t\tc: number; // close\n\t\t\t\t\tv: number; // volume\n\t\t\t\t}>;\n\t\t\t}>(\n\t\t\t\t\"defi/ohlcv\",\n\t\t\t\t{\n\t\t\t\t\taddress,\n\t\t\t\t\ttype: \"1H\", // 1 hour intervals\n\t\t\t\t\ttime_from: fromSec,\n\t\t\t\t\ttime_to: toSec,\n\t\t\t\t},\n\t\t\t\t{ chain: \"solana\" },\n\t\t\t);\n\n\t\t\tif (!ohlcvData?.items || ohlcvData.items.length === 0) {\n\t\t\t\t// Fallback to current price only\n\t\t\t\tconst currentPrice = await this.birdeyeClient.fetchPrice(address);\n\t\t\t\tif (currentPrice) {\n\t\t\t\t\treturn {\n\t\t\t\t\t\taddress,\n\t\t\t\t\t\tchain: SupportedChain.SOLANA,\n\t\t\t\t\t\tpriceHistory: [\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\ttimestamp: Date.now(),\n\t\t\t\t\t\t\t\tprice: currentPrice,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t],\n\t\t\t\t\t\tfirstPrice: currentPrice,\n\t\t\t\t\t\tlastPrice: currentPrice,\n\t\t\t\t\t\tminPrice: currentPrice,\n\t\t\t\t\t\tmaxPrice: currentPrice,\n\t\t\t\t\t\tfetchedAt: Date.now(),\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\tconst priceHistory: PricePoint[] = ohlcvData.items.map((item) => ({\n\t\t\t\ttimestamp: item.unixTime * 1000,\n\t\t\t\tprice: item.c, // Use closing price\n\t\t\t\tvolume: item.v,\n\t\t\t}));\n\n\t\t\tconst prices = priceHistory.map((p) => p.price);\n\n\t\t\treturn {\n\t\t\t\taddress,\n\t\t\t\tchain: SupportedChain.SOLANA,\n\t\t\t\tpriceHistory,\n\t\t\t\tfirstPrice: prices[0],\n\t\t\t\tlastPrice: prices[prices.length - 1],\n\t\t\t\tminPrice: Math.min(...prices),\n\t\t\t\tmaxPrice: Math.max(...prices),\n\t\t\t\tfetchedAt: Date.now(),\n\t\t\t};\n\t\t} catch (error: unknown) {\n\t\t\t// If OHLCV fails, try to get current price at least\n\t\t\tconst message = error instanceof Error ? error.message : String(error);\n\t\t\tconsole.warn(\n\t\t\t\t`OHLCV failed for ${address}, trying current price:`,\n\t\t\t\tmessage,\n\t\t\t);\n\n\t\t\ttry {\n\t\t\t\tconst currentPrice = await this.birdeyeClient.fetchPrice(address);\n\t\t\t\tif (currentPrice) {\n\t\t\t\t\treturn {\n\t\t\t\t\t\taddress,\n\t\t\t\t\t\tchain: SupportedChain.SOLANA,\n\t\t\t\t\t\tpriceHistory: [\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\ttimestamp: Date.now(),\n\t\t\t\t\t\t\t\tprice: currentPrice,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t],\n\t\t\t\t\t\tfirstPrice: currentPrice,\n\t\t\t\t\t\tlastPrice: currentPrice,\n\t\t\t\t\t\tminPrice: currentPrice,\n\t\t\t\t\t\tmaxPrice: currentPrice,\n\t\t\t\t\t\tfetchedAt: Date.now(),\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t} catch (priceError) {\n\t\t\t\tconsole.error(\n\t\t\t\t\t`Failed to get any price data for ${address}:`,\n\t\t\t\t\tpriceError,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\treturn null;\n\t\t}\n\t}\n\n\t/**\n\t * Fetch historical price data from Dexscreener\n\t * Note: DexScreener doesn't provide true historical data, only recent price changes\n\t */\n\tasync fetchDexscreenerHistoricalPrices(\n\t\taddress: string,\n\t\tchain: SupportedChain,\n\t\t_fromTimestamp: number,\n\t\t_toTimestamp: number,\n\t): Promise<HistoricalPriceData | null> {\n\t\ttry {\n\t\t\t// Search for the token\n\t\t\tconst searchResults = await this.dexscreenerClient.search(address);\n\t\t\tif (!searchResults?.pairs || searchResults.pairs.length === 0) {\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\t// Find the best pair for this chain\n\t\t\tconst chainId = this.getChainId(chain);\n\t\t\tconst pair =\n\t\t\t\tsearchResults.pairs.find(\n\t\t\t\t\t(p) =>\n\t\t\t\t\t\tp.baseToken.address.toLowerCase() === address.toLowerCase() &&\n\t\t\t\t\t\tp.chainId === chainId,\n\t\t\t\t) || searchResults.pairs[0];\n\n\t\t\tif (!pair?.priceUsd) {\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\t// Build price history from available data\n\t\t\tconst priceHistory: PricePoint[] = [];\n\t\t\tconst currentPrice = parseFloat(pair.priceUsd);\n\t\t\tconst now = Date.now();\n\n\t\t\t// Add current price\n\t\t\tpriceHistory.push({\n\t\t\t\ttimestamp: now,\n\t\t\t\tprice: currentPrice,\n\t\t\t\tvolume: pair.volume?.h24,\n\t\t\t\tliquidity: pair.liquidity?.usd,\n\t\t\t});\n\n\t\t\t// Add historical prices based on % changes\n\t\t\tif (pair.priceChange) {\n\t\t\t\t// 5 minute ago\n\t\t\t\tif (pair.priceChange.m5 !== undefined) {\n\t\t\t\t\tconst price5m = currentPrice / (1 + pair.priceChange.m5 / 100);\n\t\t\t\t\tpriceHistory.push({\n\t\t\t\t\t\ttimestamp: now - 5 * 60 * 1000,\n\t\t\t\t\t\tprice: price5m,\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\t// 1 hour ago\n\t\t\t\tif (pair.priceChange.h1 !== undefined) {\n\t\t\t\t\tconst price1h = currentPrice / (1 + pair.priceChange.h1 / 100);\n\t\t\t\t\tpriceHistory.push({\n\t\t\t\t\t\ttimestamp: now - 60 * 60 * 1000,\n\t\t\t\t\t\tprice: price1h,\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\t// 6 hours ago\n\t\t\t\tif (pair.priceChange.h6 !== undefined) {\n\t\t\t\t\tconst price6h = currentPrice / (1 + pair.priceChange.h6 / 100);\n\t\t\t\t\tpriceHistory.push({\n\t\t\t\t\t\ttimestamp: now - 6 * 60 * 60 * 1000,\n\t\t\t\t\t\tprice: price6h,\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\t// 24 hours ago\n\t\t\t\tif (pair.priceChange.h24 !== undefined) {\n\t\t\t\t\tconst price24h = currentPrice / (1 + pair.priceChange.h24 / 100);\n\t\t\t\t\tpriceHistory.push({\n\t\t\t\t\t\ttimestamp: now - 24 * 60 * 60 * 1000,\n\t\t\t\t\t\tprice: price24h,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Sort by timestamp\n\t\t\tpriceHistory.sort((a, b) => a.timestamp - b.timestamp);\n\n\t\t\tconst prices = priceHistory.map((p) => p.price);\n\n\t\t\treturn {\n\t\t\t\taddress,\n\t\t\t\tchain,\n\t\t\t\tpriceHistory,\n\t\t\t\tfirstPrice: prices[0],\n\t\t\t\tlastPrice: prices[prices.length - 1],\n\t\t\t\tminPrice: Math.min(...prices),\n\t\t\t\tmaxPrice: Math.max(...prices),\n\t\t\t\tfetchedAt: Date.now(),\n\t\t\t};\n\t\t} catch (error) {\n\t\t\tconsole.error(`Error fetching Dexscreener data for ${address}:`, error);\n\t\t\treturn null;\n\t\t}\n\t}\n\n\t/**\n\t * Get price at specific timestamp using interpolation\n\t */\n\tgetPriceAtTimestamp(\n\t\thistoricalData: HistoricalPriceData,\n\t\ttimestamp: number,\n\t): number | null {\n\t\tconst priceHistory = historicalData.priceHistory;\n\n\t\tif (priceHistory.length === 0) return null;\n\n\t\t// If timestamp is before first data point, return first price\n\t\tif (timestamp <= priceHistory[0].timestamp) {\n\t\t\treturn priceHistory[0].price;\n\t\t}\n\n\t\t// If timestamp is after last data point, return last price\n\t\tif (timestamp >= priceHistory[priceHistory.length - 1].timestamp) {\n\t\t\treturn priceHistory[priceHistory.length - 1].price;\n\t\t}\n\n\t\t// Find surrounding data points for interpolation\n\t\tfor (let i = 0; i < priceHistory.length - 1; i++) {\n\t\t\tif (\n\t\t\t\ttimestamp >= priceHistory[i].timestamp &&\n\t\t\t\ttimestamp <= priceHistory[i + 1].timestamp\n\t\t\t) {\n\t\t\t\t// Linear interpolation\n\t\t\t\tconst t1 = priceHistory[i].timestamp;\n\t\t\t\tconst t2 = priceHistory[i + 1].timestamp;\n\t\t\t\tconst p1 = priceHistory[i].price;\n\t\t\t\tconst p2 = priceHistory[i + 1].price;\n\n\t\t\t\tconst ratio = (timestamp - t1) / (t2 - t1);\n\t\t\t\treturn p1 + (p2 - p1) * ratio;\n\t\t\t}\n\t\t}\n\n\t\treturn null;\n\t}\n\n\t/**\n\t * Get max price in time window\n\t */\n\tgetMaxPriceInWindow(\n\t\thistoricalData: HistoricalPriceData,\n\t\tfromTimestamp: number,\n\t\ttoTimestamp: number,\n\t): { price: number; timestamp: number } | null {\n\t\tconst pricesInWindow = historicalData.priceHistory.filter(\n\t\t\t(p) => p.timestamp >= fromTimestamp && p.timestamp <= toTimestamp,\n\t\t);\n\n\t\tif (pricesInWindow.length === 0) {\n\t\t\t// If no data points in window, check if we can extrapolate\n\t\t\tconst priceAtStart = this.getPriceAtTimestamp(\n\t\t\t\thistoricalData,\n\t\t\t\tfromTimestamp,\n\t\t\t);\n\t\t\tconst priceAtEnd = this.getPriceAtTimestamp(historicalData, toTimestamp);\n\n\t\t\tif (priceAtStart !== null && priceAtEnd !== null) {\n\t\t\t\treturn priceAtStart >= priceAtEnd\n\t\t\t\t\t? { price: priceAtStart, timestamp: fromTimestamp }\n\t\t\t\t\t: { price: priceAtEnd, timestamp: toTimestamp };\n\t\t\t}\n\n\t\t\treturn null;\n\t\t}\n\n\t\tlet maxPrice = pricesInWindow[0];\n\t\tfor (const point of pricesInWindow) {\n\t\t\tif (point.price > maxPrice.price) {\n\t\t\t\tmaxPrice = point;\n\t\t\t}\n\t\t}\n\n\t\treturn { price: maxPrice.price, timestamp: maxPrice.timestamp };\n\t}\n\n\t/**\n\t * Search for best token match by symbol\n\t */\n\tasync findBestTokenMatch(\n\t\tsymbol: string,\n\t\tchain: SupportedChain,\n\t): Promise<TokenResolution | null> {\n\t\ttry {\n\t\t\t// Search on Dexscreener first (better for finding tokens by symbol)\n\t\t\tconst searchResults = await this.dexscreenerClient.search(symbol);\n\n\t\t\tif (!searchResults?.pairs || searchResults.pairs.length === 0) {\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\t// Filter by chain and find best match\n\t\t\tconst chainId = this.getChainId(chain);\n\t\t\tconst candidates = searchResults.pairs\n\t\t\t\t.filter(\n\t\t\t\t\t(pair) =>\n\t\t\t\t\t\tpair.chainId === chainId &&\n\t\t\t\t\t\tpair.baseToken.symbol.toUpperCase() === symbol.toUpperCase(),\n\t\t\t\t)\n\t\t\t\t.sort((a, b) => {\n\t\t\t\t\t// Sort by liquidity, then volume, then age\n\t\t\t\t\tconst liquidityA = a.liquidity?.usd || 0;\n\t\t\t\t\tconst liquidityB = b.liquidity?.usd || 0;\n\n\t\t\t\t\tif (liquidityA !== liquidityB) {\n\t\t\t\t\t\treturn liquidityB - liquidityA;\n\t\t\t\t\t}\n\n\t\t\t\t\tconst volumeA = a.volume?.h24 || 0;\n\t\t\t\t\tconst volumeB = b.volume?.h24 || 0;\n\n\t\t\t\t\tif (volumeA !== volumeB) {\n\t\t\t\t\t\treturn volumeB - volumeA;\n\t\t\t\t\t}\n\n\t\t\t\t\t// Prefer newer tokens (higher pair address usually means newer)\n\t\t\t\t\treturn (b.pairCreatedAt || 0) - (a.pairCreatedAt || 0);\n\t\t\t\t});\n\n\t\t\tif (candidates.length === 0) {\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\tconst bestMatch = candidates[0];\n\n\t\t\t// Check if it meets minimum liquidity requirements\n\t\t\tconst liquidityUsd = bestMatch.liquidity?.usd || 0;\n\t\t\tconst marketCap = bestMatch.fdv || 0;\n\t\t\tconst minLiquidityRatio = 10000 / 1000000; // $10k per $1M market cap\n\n\t\t\tif (marketCap > 0 && liquidityUsd / marketCap < minLiquidityRatio) {\n\t\t\t\tconsole.warn(\n\t\t\t\t\t`Token ${symbol} has insufficient liquidity ratio: ${liquidityUsd / marketCap}`,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\treturn {\n\t\t\t\tsymbol: bestMatch.baseToken.symbol,\n\t\t\t\taddress: bestMatch.baseToken.address,\n\t\t\t\tname: bestMatch.baseToken.name,\n\t\t\t\tchain,\n\t\t\t\tliquidity: liquidityUsd,\n\t\t\t\tvolume24h: bestMatch.volume?.h24,\n\t\t\t\tmarketCap: bestMatch.fdv,\n\t\t\t\tcreatedAt: bestMatch.pairCreatedAt,\n\t\t\t};\n\t\t} catch (error) {\n\t\t\tconsole.error(`Error finding best token match for ${symbol}:`, error);\n\t\t\treturn null;\n\t\t}\n\t}\n\n\tprivate getChainId(chain: SupportedChain): string {\n\t\tswitch (chain) {\n\t\t\tcase SupportedChain.SOLANA:\n\t\t\t\treturn \"solana\";\n\t\t\tcase SupportedChain.ETHEREUM:\n\t\t\t\treturn \"ethereum\";\n\t\t\tcase SupportedChain.BASE:\n\t\t\t\treturn \"base\";\n\t\t\tdefault:\n\t\t\t\treturn \"solana\";\n\t\t}\n\t}\n}\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export { BalancedTrustScoreCalculator } from "./balancedTrustScoreCalculator";
|
|
2
|
+
export type { HistoricalPriceData, PricePoint, TokenResolution, } from "./historicalPriceService";
|
|
3
|
+
export { HistoricalPriceService } from "./historicalPriceService";
|
|
4
|
+
export type { EnrichedTradingCall, TradingCall, TrustScore, } from "./priceEnrichmentService";
|
|
5
|
+
export { PriceEnrichmentService } from "./priceEnrichmentService";
|
|
6
|
+
export type { ActorArchetypeV2, SimulatedActorV2, SimulatedCallV2, } from "./simulationActorsV2";
|
|
7
|
+
export { SimulationActorsServiceV2 } from "./simulationActorsV2";
|
|
8
|
+
export type { ActorConfig, SimulatedCallData, SimulationConfig, SimulationResult, SimulationToken, TokenPrice, TokenScenario, } from "./simulationRunner";
|
|
9
|
+
export { SimulationRunner } from "./simulationRunner";
|
|
10
|
+
export { TokenSimulationService } from "./tokenSimulationService";
|
|
11
|
+
export { TrustScoreOptimizer } from "./trustScoreOptimizer";
|
|
12
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/services/index.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,4BAA4B,EAAE,MAAM,gCAAgC,CAAC;AAC9E,YAAY,EACX,mBAAmB,EACnB,UAAU,EACV,eAAe,GACf,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AAClE,YAAY,EACX,mBAAmB,EACnB,WAAW,EACX,UAAU,GACV,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AAElE,YAAY,EACX,gBAAgB,EAChB,gBAAgB,EAChB,eAAe,GACf,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,yBAAyB,EAAE,MAAM,sBAAsB,CAAC;AACjE,YAAY,EACX,WAAW,EACX,iBAAiB,EACjB,gBAAgB,EAChB,gBAAgB,EAChB,eAAe,EACf,UAAU,EACV,aAAa,GACb,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AAClE,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { BalancedTrustScoreCalculator } from "./balancedTrustScoreCalculator.js";
|
|
2
|
+
import { HistoricalPriceService } from "./historicalPriceService.js";
|
|
3
|
+
import { PriceEnrichmentService } from "./priceEnrichmentService.js";
|
|
4
|
+
import { SimulationActorsServiceV2 } from "./simulationActorsV2.js";
|
|
5
|
+
import { SimulationRunner } from "./simulationRunner.js";
|
|
6
|
+
import { TokenSimulationService } from "./tokenSimulationService.js";
|
|
7
|
+
import { TrustScoreOptimizer } from "./trustScoreOptimizer.js";
|
|
8
|
+
export {
|
|
9
|
+
BalancedTrustScoreCalculator,
|
|
10
|
+
HistoricalPriceService,
|
|
11
|
+
PriceEnrichmentService,
|
|
12
|
+
SimulationActorsServiceV2,
|
|
13
|
+
SimulationRunner,
|
|
14
|
+
TokenSimulationService,
|
|
15
|
+
TrustScoreOptimizer
|
|
16
|
+
};
|
|
17
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/services/index.ts"],"sourcesContent":["// Services\n\n// Original Services (kept for backward compatibility during migration)\nexport { BalancedTrustScoreCalculator } from \"./balancedTrustScoreCalculator.js\";\nexport type {\n\tHistoricalPriceData,\n\tPricePoint,\n\tTokenResolution,\n} from \"./historicalPriceService.js\";\nexport { HistoricalPriceService } from \"./historicalPriceService.js\";\nexport type {\n\tEnrichedTradingCall,\n\tTradingCall,\n\tTrustScore,\n} from \"./priceEnrichmentService.js\";\nexport { PriceEnrichmentService } from \"./priceEnrichmentService.js\";\n// Re-export types from services\nexport type {\n\tActorArchetypeV2,\n\tSimulatedActorV2,\n\tSimulatedCallV2,\n} from \"./simulationActorsV2.js\";\nexport { SimulationActorsServiceV2 } from \"./simulationActorsV2.js\";\nexport type {\n\tActorConfig,\n\tSimulatedCallData,\n\tSimulationConfig,\n\tSimulationResult,\n\tSimulationToken,\n\tTokenPrice,\n\tTokenScenario,\n} from \"./simulationRunner.js\";\nexport { SimulationRunner } from \"./simulationRunner.js\";\nexport { TokenSimulationService } from \"./tokenSimulationService.js\";\nexport { TrustScoreOptimizer } from \"./trustScoreOptimizer.js\";\n"],"mappings":"AAGA,SAAS,oCAAoC;AAM7C,SAAS,8BAA8B;AAMvC,SAAS,8BAA8B;AAOvC,SAAS,iCAAiC;AAU1C,SAAS,wBAAwB;AACjC,SAAS,8BAA8B;AACvC,SAAS,2BAA2B;","names":[]}
|