thecrownsk-bot 1.0.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/LICENSE +21 -0
- package/README.md +268 -0
- package/dist/blockchain/chain.d.ts +49 -0
- package/dist/blockchain/chain.d.ts.map +1 -0
- package/dist/blockchain/chain.js +33 -0
- package/dist/blockchain/chain.js.map +1 -0
- package/dist/blockchain/client.d.ts +19 -0
- package/dist/blockchain/client.d.ts.map +1 -0
- package/dist/blockchain/client.js +121 -0
- package/dist/blockchain/client.js.map +1 -0
- package/dist/config/constants.d.ts +53 -0
- package/dist/config/constants.d.ts.map +1 -0
- package/dist/config/constants.js +61 -0
- package/dist/config/constants.js.map +1 -0
- package/dist/config/env.d.ts +38 -0
- package/dist/config/env.d.ts.map +1 -0
- package/dist/config/env.js +38 -0
- package/dist/config/env.js.map +1 -0
- package/dist/crown-king.d.ts +3 -0
- package/dist/crown-king.d.ts.map +1 -0
- package/dist/crown-king.js +1093 -0
- package/dist/crown-king.js.map +1 -0
- package/dist/crownking/agent-alliance.d.ts +49 -0
- package/dist/crownking/agent-alliance.d.ts.map +1 -0
- package/dist/crownking/agent-alliance.js +260 -0
- package/dist/crownking/agent-alliance.js.map +1 -0
- package/dist/crownking/agent.d.ts +77 -0
- package/dist/crownking/agent.d.ts.map +1 -0
- package/dist/crownking/agent.js +361 -0
- package/dist/crownking/agent.js.map +1 -0
- package/dist/crownking/auto-poster.d.ts +43 -0
- package/dist/crownking/auto-poster.d.ts.map +1 -0
- package/dist/crownking/auto-poster.js +179 -0
- package/dist/crownking/auto-poster.js.map +1 -0
- package/dist/crownking/contract.d.ts +62 -0
- package/dist/crownking/contract.d.ts.map +1 -0
- package/dist/crownking/contract.js +130 -0
- package/dist/crownking/contract.js.map +1 -0
- package/dist/crownking/copy-trader.d.ts +77 -0
- package/dist/crownking/copy-trader.d.ts.map +1 -0
- package/dist/crownking/copy-trader.js +265 -0
- package/dist/crownking/copy-trader.js.map +1 -0
- package/dist/crownking/index.d.ts +16 -0
- package/dist/crownking/index.d.ts.map +1 -0
- package/dist/crownking/index.js +18 -0
- package/dist/crownking/index.js.map +1 -0
- package/dist/crownking/leaderboard.d.ts +51 -0
- package/dist/crownking/leaderboard.d.ts.map +1 -0
- package/dist/crownking/leaderboard.js +213 -0
- package/dist/crownking/leaderboard.js.map +1 -0
- package/dist/crownking/live-scanner.d.ts +85 -0
- package/dist/crownking/live-scanner.d.ts.map +1 -0
- package/dist/crownking/live-scanner.js +345 -0
- package/dist/crownking/live-scanner.js.map +1 -0
- package/dist/crownking/momentum.d.ts +41 -0
- package/dist/crownking/momentum.d.ts.map +1 -0
- package/dist/crownking/momentum.js +251 -0
- package/dist/crownking/momentum.js.map +1 -0
- package/dist/crownking/personality.d.ts +77 -0
- package/dist/crownking/personality.d.ts.map +1 -0
- package/dist/crownking/personality.js +222 -0
- package/dist/crownking/personality.js.map +1 -0
- package/dist/crownking/portfolio.d.ts +62 -0
- package/dist/crownking/portfolio.d.ts.map +1 -0
- package/dist/crownking/portfolio.js +183 -0
- package/dist/crownking/portfolio.js.map +1 -0
- package/dist/crownking/sniper.d.ts +68 -0
- package/dist/crownking/sniper.d.ts.map +1 -0
- package/dist/crownking/sniper.js +264 -0
- package/dist/crownking/sniper.js.map +1 -0
- package/dist/crownking/social-graph.d.ts +72 -0
- package/dist/crownking/social-graph.d.ts.map +1 -0
- package/dist/crownking/social-graph.js +219 -0
- package/dist/crownking/social-graph.js.map +1 -0
- package/dist/crownking/token-creator.d.ts +42 -0
- package/dist/crownking/token-creator.d.ts.map +1 -0
- package/dist/crownking/token-creator.js +159 -0
- package/dist/crownking/token-creator.js.map +1 -0
- package/dist/crownking/trading-signals.d.ts +56 -0
- package/dist/crownking/trading-signals.d.ts.map +1 -0
- package/dist/crownking/trading-signals.js +253 -0
- package/dist/crownking/trading-signals.js.map +1 -0
- package/dist/crownking/types.d.ts +3 -0
- package/dist/crownking/types.d.ts.map +1 -0
- package/dist/crownking/types.js +4 -0
- package/dist/crownking/types.js.map +1 -0
- package/dist/crownking/whale-tracker.d.ts +53 -0
- package/dist/crownking/whale-tracker.d.ts.map +1 -0
- package/dist/crownking/whale-tracker.js +188 -0
- package/dist/crownking/whale-tracker.js.map +1 -0
- package/dist/crownsk/agent-alliance.d.ts +49 -0
- package/dist/crownsk/agent-alliance.d.ts.map +1 -0
- package/dist/crownsk/agent-alliance.js +260 -0
- package/dist/crownsk/agent-alliance.js.map +1 -0
- package/dist/crownsk/agent.d.ts +77 -0
- package/dist/crownsk/agent.d.ts.map +1 -0
- package/dist/crownsk/agent.js +361 -0
- package/dist/crownsk/agent.js.map +1 -0
- package/dist/crownsk/auto-poster.d.ts +43 -0
- package/dist/crownsk/auto-poster.d.ts.map +1 -0
- package/dist/crownsk/auto-poster.js +179 -0
- package/dist/crownsk/auto-poster.js.map +1 -0
- package/dist/crownsk/contract.d.ts +62 -0
- package/dist/crownsk/contract.d.ts.map +1 -0
- package/dist/crownsk/contract.js +130 -0
- package/dist/crownsk/contract.js.map +1 -0
- package/dist/crownsk/copy-trader.d.ts +77 -0
- package/dist/crownsk/copy-trader.d.ts.map +1 -0
- package/dist/crownsk/copy-trader.js +265 -0
- package/dist/crownsk/copy-trader.js.map +1 -0
- package/dist/crownsk/index.d.ts +16 -0
- package/dist/crownsk/index.d.ts.map +1 -0
- package/dist/crownsk/index.js +18 -0
- package/dist/crownsk/index.js.map +1 -0
- package/dist/crownsk/leaderboard.d.ts +51 -0
- package/dist/crownsk/leaderboard.d.ts.map +1 -0
- package/dist/crownsk/leaderboard.js +213 -0
- package/dist/crownsk/leaderboard.js.map +1 -0
- package/dist/crownsk/live-scanner.d.ts +85 -0
- package/dist/crownsk/live-scanner.d.ts.map +1 -0
- package/dist/crownsk/live-scanner.js +345 -0
- package/dist/crownsk/live-scanner.js.map +1 -0
- package/dist/crownsk/momentum.d.ts +41 -0
- package/dist/crownsk/momentum.d.ts.map +1 -0
- package/dist/crownsk/momentum.js +251 -0
- package/dist/crownsk/momentum.js.map +1 -0
- package/dist/crownsk/personality.d.ts +77 -0
- package/dist/crownsk/personality.d.ts.map +1 -0
- package/dist/crownsk/personality.js +222 -0
- package/dist/crownsk/personality.js.map +1 -0
- package/dist/crownsk/portfolio.d.ts +62 -0
- package/dist/crownsk/portfolio.d.ts.map +1 -0
- package/dist/crownsk/portfolio.js +183 -0
- package/dist/crownsk/portfolio.js.map +1 -0
- package/dist/crownsk/sniper.d.ts +68 -0
- package/dist/crownsk/sniper.d.ts.map +1 -0
- package/dist/crownsk/sniper.js +264 -0
- package/dist/crownsk/sniper.js.map +1 -0
- package/dist/crownsk/social-graph.d.ts +72 -0
- package/dist/crownsk/social-graph.d.ts.map +1 -0
- package/dist/crownsk/social-graph.js +219 -0
- package/dist/crownsk/social-graph.js.map +1 -0
- package/dist/crownsk/trading-signals.d.ts +56 -0
- package/dist/crownsk/trading-signals.d.ts.map +1 -0
- package/dist/crownsk/trading-signals.js +253 -0
- package/dist/crownsk/trading-signals.js.map +1 -0
- package/dist/crownsk/types.d.ts +3 -0
- package/dist/crownsk/types.d.ts.map +1 -0
- package/dist/crownsk/types.js +4 -0
- package/dist/crownsk/types.js.map +1 -0
- package/dist/crownsk/whale-tracker.d.ts +53 -0
- package/dist/crownsk/whale-tracker.d.ts.map +1 -0
- package/dist/crownsk/whale-tracker.js +188 -0
- package/dist/crownsk/whale-tracker.js.map +1 -0
- package/dist/crownsk.d.ts +3 -0
- package/dist/crownsk.d.ts.map +1 -0
- package/dist/crownsk.js +1102 -0
- package/dist/crownsk.js.map +1 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +9 -0
- package/dist/index.js.map +1 -0
- package/dist/karma/agent.d.ts +81 -0
- package/dist/karma/agent.d.ts.map +1 -0
- package/dist/karma/agent.js +366 -0
- package/dist/karma/agent.js.map +1 -0
- package/dist/karma/contract.d.ts +62 -0
- package/dist/karma/contract.d.ts.map +1 -0
- package/dist/karma/contract.js +130 -0
- package/dist/karma/contract.js.map +1 -0
- package/dist/karma/index.d.ts +6 -0
- package/dist/karma/index.d.ts.map +1 -0
- package/dist/karma/index.js +7 -0
- package/dist/karma/index.js.map +1 -0
- package/dist/karma/live-scanner.d.ts +85 -0
- package/dist/karma/live-scanner.d.ts.map +1 -0
- package/dist/karma/live-scanner.js +345 -0
- package/dist/karma/live-scanner.js.map +1 -0
- package/dist/karma/social-graph.d.ts +72 -0
- package/dist/karma/social-graph.d.ts.map +1 -0
- package/dist/karma/social-graph.js +219 -0
- package/dist/karma/social-graph.js.map +1 -0
- package/dist/karma/trading-signals.d.ts +38 -0
- package/dist/karma/trading-signals.d.ts.map +1 -0
- package/dist/karma/trading-signals.js +291 -0
- package/dist/karma/trading-signals.js.map +1 -0
- package/dist/karma/types.d.ts +3 -0
- package/dist/karma/types.d.ts.map +1 -0
- package/dist/karma/types.js +4 -0
- package/dist/karma/types.js.map +1 -0
- package/dist/karma-king.d.ts +3 -0
- package/dist/karma-king.d.ts.map +1 -0
- package/dist/karma-king.js +580 -0
- package/dist/karma-king.js.map +1 -0
- package/dist/moltbook/client.d.ts +34 -0
- package/dist/moltbook/client.d.ts.map +1 -0
- package/dist/moltbook/client.js +280 -0
- package/dist/moltbook/client.js.map +1 -0
- package/dist/moltbook/index.d.ts +3 -0
- package/dist/moltbook/index.d.ts.map +1 -0
- package/dist/moltbook/index.js +4 -0
- package/dist/moltbook/index.js.map +1 -0
- package/dist/moltbook/types.d.ts +100 -0
- package/dist/moltbook/types.d.ts.map +1 -0
- package/dist/moltbook/types.js +3 -0
- package/dist/moltbook/types.js.map +1 -0
- package/dist/nadfun/abis.d.ts +403 -0
- package/dist/nadfun/abis.d.ts.map +1 -0
- package/dist/nadfun/abis.js +267 -0
- package/dist/nadfun/abis.js.map +1 -0
- package/dist/nadfun/client.d.ts +21 -0
- package/dist/nadfun/client.d.ts.map +1 -0
- package/dist/nadfun/client.js +349 -0
- package/dist/nadfun/client.js.map +1 -0
- package/dist/nadfun/index.d.ts +5 -0
- package/dist/nadfun/index.d.ts.map +1 -0
- package/dist/nadfun/index.js +5 -0
- package/dist/nadfun/index.js.map +1 -0
- package/dist/nadfun/types.d.ts +72 -0
- package/dist/nadfun/types.d.ts.map +1 -0
- package/dist/nadfun/types.js +2 -0
- package/dist/nadfun/types.js.map +1 -0
- package/dist/nadfun/websocket.d.ts +18 -0
- package/dist/nadfun/websocket.d.ts.map +1 -0
- package/dist/nadfun/websocket.js +110 -0
- package/dist/nadfun/websocket.js.map +1 -0
- package/dist/utils/format.d.ts +9 -0
- package/dist/utils/format.d.ts.map +1 -0
- package/dist/utils/format.js +39 -0
- package/dist/utils/format.js.map +1 -0
- package/dist/utils/index.d.ts +3 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +3 -0
- package/dist/utils/index.js.map +1 -0
- package/dist/utils/logger.d.ts +3 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +81 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/wallet/manager.d.ts +76 -0
- package/dist/wallet/manager.d.ts.map +1 -0
- package/dist/wallet/manager.js +300 -0
- package/dist/wallet/manager.js.map +1 -0
- package/package.json +61 -0
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
// Leaderboard Module
|
|
2
|
+
// Track CrownKing's position and compete with other agents
|
|
3
|
+
import { moltbookClient } from '../moltbook/client.js';
|
|
4
|
+
import { logger } from '../utils/logger.js';
|
|
5
|
+
// Track agent rankings over time
|
|
6
|
+
const rankingHistory = [];
|
|
7
|
+
let cachedLeaderboard = null;
|
|
8
|
+
let lastFetchTime = 0;
|
|
9
|
+
const CACHE_DURATION = 5 * 60 * 1000; // 5 minutes
|
|
10
|
+
/**
|
|
11
|
+
* Fetch and calculate leaderboard position
|
|
12
|
+
*/
|
|
13
|
+
export async function fetchLeaderboard() {
|
|
14
|
+
if (cachedLeaderboard && Date.now() - lastFetchTime < CACHE_DURATION) {
|
|
15
|
+
return cachedLeaderboard;
|
|
16
|
+
}
|
|
17
|
+
if (!moltbookClient.isRegistered()) {
|
|
18
|
+
return {
|
|
19
|
+
myRank: null,
|
|
20
|
+
myKarma: 0,
|
|
21
|
+
myFollowers: 0,
|
|
22
|
+
topAgents: [],
|
|
23
|
+
nearbyAgents: [],
|
|
24
|
+
totalAgents: 0,
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
try {
|
|
28
|
+
// Get my agent info
|
|
29
|
+
const me = await moltbookClient.getMe();
|
|
30
|
+
// Get feed to discover other agents
|
|
31
|
+
const feed = await moltbookClient.getFeed();
|
|
32
|
+
// Build agent list from feed authors
|
|
33
|
+
const agentMap = new Map();
|
|
34
|
+
for (const post of feed.posts) {
|
|
35
|
+
if (!agentMap.has(post.author.id)) {
|
|
36
|
+
agentMap.set(post.author.id, {
|
|
37
|
+
agentId: post.author.id,
|
|
38
|
+
agentName: post.author.name,
|
|
39
|
+
karma: post.author.karma,
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
// Add self
|
|
44
|
+
agentMap.set(me.id, {
|
|
45
|
+
agentId: me.id,
|
|
46
|
+
agentName: me.name,
|
|
47
|
+
karma: me.karma,
|
|
48
|
+
});
|
|
49
|
+
// Sort by karma
|
|
50
|
+
const sortedAgents = Array.from(agentMap.values())
|
|
51
|
+
.sort((a, b) => b.karma - a.karma);
|
|
52
|
+
// Calculate rankings
|
|
53
|
+
const rankings = sortedAgents.map((agent, index) => ({
|
|
54
|
+
rank: index + 1,
|
|
55
|
+
agentId: agent.agentId,
|
|
56
|
+
agentName: agent.agentName,
|
|
57
|
+
karma: agent.karma,
|
|
58
|
+
followers: 0, // Not available from feed
|
|
59
|
+
posts: 0, // Not available from feed
|
|
60
|
+
isMe: agent.agentId === me.id,
|
|
61
|
+
}));
|
|
62
|
+
// Find my rank
|
|
63
|
+
const myRanking = rankings.find(r => r.isMe);
|
|
64
|
+
const myRank = myRanking?.rank || null;
|
|
65
|
+
// Get nearby agents (2 above and 2 below)
|
|
66
|
+
let nearbyAgents = [];
|
|
67
|
+
if (myRank) {
|
|
68
|
+
const startIdx = Math.max(0, myRank - 3);
|
|
69
|
+
const endIdx = Math.min(rankings.length, myRank + 2);
|
|
70
|
+
nearbyAgents = rankings.slice(startIdx, endIdx);
|
|
71
|
+
}
|
|
72
|
+
// Record ranking history
|
|
73
|
+
if (myRank) {
|
|
74
|
+
rankingHistory.push({
|
|
75
|
+
timestamp: Date.now(),
|
|
76
|
+
rank: myRank,
|
|
77
|
+
karma: me.karma,
|
|
78
|
+
});
|
|
79
|
+
// Keep only last 100 entries
|
|
80
|
+
if (rankingHistory.length > 100) {
|
|
81
|
+
rankingHistory.shift();
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
const stats = {
|
|
85
|
+
myRank,
|
|
86
|
+
myKarma: me.karma,
|
|
87
|
+
myFollowers: 0, // Would need to fetch
|
|
88
|
+
topAgents: rankings.slice(0, 10),
|
|
89
|
+
nearbyAgents,
|
|
90
|
+
totalAgents: rankings.length,
|
|
91
|
+
};
|
|
92
|
+
cachedLeaderboard = stats;
|
|
93
|
+
lastFetchTime = Date.now();
|
|
94
|
+
logger.info('Leaderboard updated', { myRank, totalAgents: rankings.length });
|
|
95
|
+
return stats;
|
|
96
|
+
}
|
|
97
|
+
catch (error) {
|
|
98
|
+
logger.warn('Failed to fetch leaderboard', { error: error instanceof Error ? error.message : String(error) });
|
|
99
|
+
return cachedLeaderboard || {
|
|
100
|
+
myRank: null,
|
|
101
|
+
myKarma: 0,
|
|
102
|
+
myFollowers: 0,
|
|
103
|
+
topAgents: [],
|
|
104
|
+
nearbyAgents: [],
|
|
105
|
+
totalAgents: 0,
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Get ranking trend (improving or declining)
|
|
111
|
+
*/
|
|
112
|
+
export function getRankingTrend() {
|
|
113
|
+
if (rankingHistory.length < 2) {
|
|
114
|
+
return { direction: 'stable', change: 0, periodHours: 0 };
|
|
115
|
+
}
|
|
116
|
+
const oldest = rankingHistory[0];
|
|
117
|
+
const newest = rankingHistory[rankingHistory.length - 1];
|
|
118
|
+
const rankChange = oldest.rank - newest.rank; // Positive = improved (lower rank number is better)
|
|
119
|
+
const periodHours = (newest.timestamp - oldest.timestamp) / (1000 * 60 * 60);
|
|
120
|
+
return {
|
|
121
|
+
direction: rankChange > 0 ? 'up' : rankChange < 0 ? 'down' : 'stable',
|
|
122
|
+
change: Math.abs(rankChange),
|
|
123
|
+
periodHours: Math.round(periodHours * 10) / 10,
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Get karma growth rate
|
|
128
|
+
*/
|
|
129
|
+
export function getKarmaGrowth() {
|
|
130
|
+
if (rankingHistory.length < 2) {
|
|
131
|
+
return { growth: 0, ratePerHour: 0 };
|
|
132
|
+
}
|
|
133
|
+
const oldest = rankingHistory[0];
|
|
134
|
+
const newest = rankingHistory[rankingHistory.length - 1];
|
|
135
|
+
const growth = newest.karma - oldest.karma;
|
|
136
|
+
const hours = (newest.timestamp - oldest.timestamp) / (1000 * 60 * 60);
|
|
137
|
+
const ratePerHour = hours > 0 ? growth / hours : 0;
|
|
138
|
+
return {
|
|
139
|
+
growth,
|
|
140
|
+
ratePerHour: Math.round(ratePerHour * 100) / 100,
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Get competitive insights
|
|
145
|
+
*/
|
|
146
|
+
export async function getCompetitiveInsights() {
|
|
147
|
+
const leaderboard = await fetchLeaderboard();
|
|
148
|
+
const insights = {
|
|
149
|
+
rank: leaderboard.myRank,
|
|
150
|
+
karmaToNextRank: 0,
|
|
151
|
+
nearestCompetitor: null,
|
|
152
|
+
strengths: [],
|
|
153
|
+
opportunities: [],
|
|
154
|
+
};
|
|
155
|
+
if (!leaderboard.myRank || leaderboard.topAgents.length === 0) {
|
|
156
|
+
return insights;
|
|
157
|
+
}
|
|
158
|
+
// Find karma needed to rank up
|
|
159
|
+
if (leaderboard.myRank > 1) {
|
|
160
|
+
const above = leaderboard.nearbyAgents.find(a => a.rank === leaderboard.myRank - 1);
|
|
161
|
+
if (above) {
|
|
162
|
+
insights.karmaToNextRank = above.karma - leaderboard.myKarma + 1;
|
|
163
|
+
insights.nearestCompetitor = above.agentName;
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
// Analyze strengths
|
|
167
|
+
const trend = getRankingTrend();
|
|
168
|
+
if (trend.direction === 'up') {
|
|
169
|
+
insights.strengths.push(`Ranking improved by ${trend.change} positions`);
|
|
170
|
+
}
|
|
171
|
+
const growth = getKarmaGrowth();
|
|
172
|
+
if (growth.ratePerHour > 1) {
|
|
173
|
+
insights.strengths.push(`Karma growing at ${growth.ratePerHour}/hr`);
|
|
174
|
+
}
|
|
175
|
+
// Identify opportunities
|
|
176
|
+
if (insights.karmaToNextRank > 0 && insights.karmaToNextRank <= 10) {
|
|
177
|
+
insights.opportunities.push(`Only ${insights.karmaToNextRank} karma to reach rank ${leaderboard.myRank - 1}`);
|
|
178
|
+
}
|
|
179
|
+
if (leaderboard.myRank > 5) {
|
|
180
|
+
insights.opportunities.push('Post more quality content to climb rankings');
|
|
181
|
+
}
|
|
182
|
+
return insights;
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* Format leaderboard for display
|
|
186
|
+
*/
|
|
187
|
+
export function formatLeaderboard(stats) {
|
|
188
|
+
const lines = [];
|
|
189
|
+
lines.push('=== 🏆 LEADERBOARD ===');
|
|
190
|
+
lines.push(`Your Rank: #${stats.myRank || 'Unranked'} / ${stats.totalAgents}`);
|
|
191
|
+
lines.push(`Your Karma: ${stats.myKarma}`);
|
|
192
|
+
if (stats.topAgents.length > 0) {
|
|
193
|
+
lines.push('\n--- Top Agents ---');
|
|
194
|
+
for (const agent of stats.topAgents.slice(0, 5)) {
|
|
195
|
+
const marker = agent.isMe ? ' 👑' : '';
|
|
196
|
+
lines.push(`#${agent.rank} ${agent.agentName} (${agent.karma} karma)${marker}`);
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
if (stats.nearbyAgents.length > 0 && stats.myRank && stats.myRank > 5) {
|
|
200
|
+
lines.push('\n--- Your Competition ---');
|
|
201
|
+
for (const agent of stats.nearbyAgents) {
|
|
202
|
+
const marker = agent.isMe ? ' 👑 (YOU)' : '';
|
|
203
|
+
lines.push(`#${agent.rank} ${agent.agentName} (${agent.karma} karma)${marker}`);
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
const trend = getRankingTrend();
|
|
207
|
+
if (trend.direction !== 'stable') {
|
|
208
|
+
const emoji = trend.direction === 'up' ? '📈' : '📉';
|
|
209
|
+
lines.push(`\n${emoji} Trend: ${trend.direction === 'up' ? '+' : '-'}${trend.change} ranks over ${trend.periodHours}h`);
|
|
210
|
+
}
|
|
211
|
+
return lines.join('\n');
|
|
212
|
+
}
|
|
213
|
+
//# sourceMappingURL=leaderboard.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"leaderboard.js","sourceRoot":"","sources":["../../src/crownking/leaderboard.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { type Address } from 'viem';
|
|
2
|
+
export interface LiveToken {
|
|
3
|
+
address: Address;
|
|
4
|
+
name: string;
|
|
5
|
+
symbol: string;
|
|
6
|
+
creator: Address;
|
|
7
|
+
createdAt: number;
|
|
8
|
+
graduated: boolean;
|
|
9
|
+
progress: number;
|
|
10
|
+
marketCap?: string;
|
|
11
|
+
volume24h?: string;
|
|
12
|
+
priceChange24h?: number;
|
|
13
|
+
holders?: number;
|
|
14
|
+
imageUri?: string;
|
|
15
|
+
description?: string;
|
|
16
|
+
}
|
|
17
|
+
export interface TokenActivity {
|
|
18
|
+
token: Address;
|
|
19
|
+
type: 'buy' | 'sell' | 'create';
|
|
20
|
+
amount: bigint;
|
|
21
|
+
user: Address;
|
|
22
|
+
timestamp: number;
|
|
23
|
+
txHash: string;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Fetch tokens by creation time (newest first)
|
|
27
|
+
*/
|
|
28
|
+
export declare function fetchNewTokens(limit?: number): Promise<LiveToken[]>;
|
|
29
|
+
/**
|
|
30
|
+
* Fetch tokens by market cap (top tokens)
|
|
31
|
+
*/
|
|
32
|
+
export declare function fetchTrendingTokens(limit?: number): Promise<LiveToken[]>;
|
|
33
|
+
/**
|
|
34
|
+
* Fetch tokens by market cap
|
|
35
|
+
*/
|
|
36
|
+
export declare function fetchTopTokens(limit?: number): Promise<LiveToken[]>;
|
|
37
|
+
/**
|
|
38
|
+
* Get single token market info from API
|
|
39
|
+
*/
|
|
40
|
+
export declare function getTokenMarketInfo(tokenAddress: Address): Promise<{
|
|
41
|
+
marketType: 'CURVE' | 'DEX';
|
|
42
|
+
reserveNative: bigint;
|
|
43
|
+
reserveToken: bigint;
|
|
44
|
+
price: string;
|
|
45
|
+
priceUsd: string;
|
|
46
|
+
holders: number;
|
|
47
|
+
} | null>;
|
|
48
|
+
/**
|
|
49
|
+
* Get token info directly from blockchain
|
|
50
|
+
*/
|
|
51
|
+
export declare function getTokenInfoOnChain(tokenAddress: Address): Promise<LiveToken | null>;
|
|
52
|
+
/**
|
|
53
|
+
* Fetch recent token activity (placeholder - would need websocket or indexer)
|
|
54
|
+
*/
|
|
55
|
+
export declare function fetchTokenActivity(_tokenAddress?: Address, _limit?: number): Promise<TokenActivity[]>;
|
|
56
|
+
/**
|
|
57
|
+
* Analyze token for trading signal
|
|
58
|
+
*/
|
|
59
|
+
export declare function analyzeToken(tokenAddress: Address): Promise<{
|
|
60
|
+
token: Address;
|
|
61
|
+
score: number;
|
|
62
|
+
signals: string[];
|
|
63
|
+
recommendation: 'buy' | 'sell' | 'hold';
|
|
64
|
+
marketInfo?: Awaited<ReturnType<typeof getTokenMarketInfo>>;
|
|
65
|
+
}>;
|
|
66
|
+
/**
|
|
67
|
+
* Fetch tokens from on-chain events (fallback when API unavailable)
|
|
68
|
+
*/
|
|
69
|
+
export declare function fetchTokensFromChain(limit?: number): Promise<LiveToken[]>;
|
|
70
|
+
/**
|
|
71
|
+
* Scan for live trading opportunities
|
|
72
|
+
*/
|
|
73
|
+
export declare function scanLiveOpportunities(): Promise<Array<{
|
|
74
|
+
token: LiveToken;
|
|
75
|
+
analysis: Awaited<ReturnType<typeof analyzeToken>>;
|
|
76
|
+
}>>;
|
|
77
|
+
/**
|
|
78
|
+
* Get wallet token holdings
|
|
79
|
+
*/
|
|
80
|
+
export declare function getWalletTokens(_walletAddress: Address): Promise<Array<{
|
|
81
|
+
token: Address;
|
|
82
|
+
balance: bigint;
|
|
83
|
+
value?: bigint;
|
|
84
|
+
}>>;
|
|
85
|
+
//# sourceMappingURL=live-scanner.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"live-scanner.d.ts","sourceRoot":"","sources":["../../src/crownking/live-scanner.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,345 @@
|
|
|
1
|
+
// Live Data Scanner for KarmaKing
|
|
2
|
+
// Fetches real token data from nad.fun API and blockchain
|
|
3
|
+
import { parseAbiItem } from 'viem';
|
|
4
|
+
import { getPublicClient } from '../blockchain/client.js';
|
|
5
|
+
import { getTokenStatus, getAmountOut } from '../nadfun/client.js';
|
|
6
|
+
import { NADFUN_CONTRACTS, NADFUN_API_BASE, NADFUN_ENDPOINTS } from '../config/constants.js';
|
|
7
|
+
import { logger } from '../utils/logger.js';
|
|
8
|
+
const API_BASE = NADFUN_API_BASE;
|
|
9
|
+
/**
|
|
10
|
+
* Convert nad.fun API response to LiveToken
|
|
11
|
+
*/
|
|
12
|
+
function convertToLiveToken(data) {
|
|
13
|
+
return {
|
|
14
|
+
address: data.token_info.token_id,
|
|
15
|
+
name: data.token_info.name,
|
|
16
|
+
symbol: data.token_info.symbol,
|
|
17
|
+
creator: data.token_info.creator.account_id,
|
|
18
|
+
createdAt: data.token_info.created_at * 1000,
|
|
19
|
+
graduated: data.token_info.is_graduated || data.market_info.market_type === 'DEX',
|
|
20
|
+
progress: data.percent || 0,
|
|
21
|
+
marketCap: data.market_info.price_usd,
|
|
22
|
+
volume24h: data.market_info.volume,
|
|
23
|
+
holders: data.market_info.holder_count,
|
|
24
|
+
imageUri: data.token_info.image_uri,
|
|
25
|
+
description: data.token_info.description,
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Fetch tokens by creation time (newest first)
|
|
30
|
+
*/
|
|
31
|
+
export async function fetchNewTokens(limit = 20) {
|
|
32
|
+
try {
|
|
33
|
+
const response = await fetch(`${API_BASE}${NADFUN_ENDPOINTS.TOKENS_BY_CREATION}?limit=${limit}`);
|
|
34
|
+
if (!response.ok) {
|
|
35
|
+
throw new Error(`API error: ${response.status}`);
|
|
36
|
+
}
|
|
37
|
+
const data = await response.json();
|
|
38
|
+
const tokens = data.tokens?.map(convertToLiveToken) || [];
|
|
39
|
+
logger.info('Fetched new tokens from API', { count: tokens.length, total: data.total_count });
|
|
40
|
+
return tokens;
|
|
41
|
+
}
|
|
42
|
+
catch (error) {
|
|
43
|
+
logger.warn('Failed to fetch new tokens from API', {
|
|
44
|
+
error: error instanceof Error ? error.message : String(error)
|
|
45
|
+
});
|
|
46
|
+
return [];
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Fetch tokens by market cap (top tokens)
|
|
51
|
+
*/
|
|
52
|
+
export async function fetchTrendingTokens(limit = 20) {
|
|
53
|
+
try {
|
|
54
|
+
const response = await fetch(`${API_BASE}${NADFUN_ENDPOINTS.TOKENS_BY_MARKET_CAP}?limit=${limit}`);
|
|
55
|
+
if (!response.ok) {
|
|
56
|
+
throw new Error(`API error: ${response.status}`);
|
|
57
|
+
}
|
|
58
|
+
const data = await response.json();
|
|
59
|
+
const tokens = data.tokens?.map(convertToLiveToken) || [];
|
|
60
|
+
logger.info('Fetched trending tokens by market cap', { count: tokens.length });
|
|
61
|
+
return tokens;
|
|
62
|
+
}
|
|
63
|
+
catch (error) {
|
|
64
|
+
logger.warn('Failed to fetch trending tokens from API', {
|
|
65
|
+
error: error instanceof Error ? error.message : String(error)
|
|
66
|
+
});
|
|
67
|
+
return [];
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Fetch tokens by market cap
|
|
72
|
+
*/
|
|
73
|
+
export async function fetchTopTokens(limit = 20) {
|
|
74
|
+
try {
|
|
75
|
+
const response = await fetch(`${API_BASE}${NADFUN_ENDPOINTS.TOKENS_BY_MARKET_CAP}?limit=${limit}`);
|
|
76
|
+
if (!response.ok) {
|
|
77
|
+
throw new Error(`API error: ${response.status}`);
|
|
78
|
+
}
|
|
79
|
+
const data = await response.json();
|
|
80
|
+
const tokens = data.tokens?.map(convertToLiveToken) || [];
|
|
81
|
+
logger.info('Fetched top tokens by market cap', { count: tokens.length });
|
|
82
|
+
return tokens;
|
|
83
|
+
}
|
|
84
|
+
catch (error) {
|
|
85
|
+
logger.warn('Failed to fetch top tokens from API', {
|
|
86
|
+
error: error instanceof Error ? error.message : String(error)
|
|
87
|
+
});
|
|
88
|
+
return [];
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Get single token market info from API
|
|
93
|
+
*/
|
|
94
|
+
export async function getTokenMarketInfo(tokenAddress) {
|
|
95
|
+
try {
|
|
96
|
+
const response = await fetch(`${API_BASE}${NADFUN_ENDPOINTS.TOKEN_MARKET}/${tokenAddress}`);
|
|
97
|
+
if (!response.ok) {
|
|
98
|
+
if (response.status === 404) {
|
|
99
|
+
return null;
|
|
100
|
+
}
|
|
101
|
+
throw new Error(`API error: ${response.status}`);
|
|
102
|
+
}
|
|
103
|
+
const data = await response.json();
|
|
104
|
+
return {
|
|
105
|
+
marketType: data.market_info.market_type,
|
|
106
|
+
reserveNative: BigInt(data.market_info.reserve_native),
|
|
107
|
+
reserveToken: BigInt(data.market_info.reserve_token),
|
|
108
|
+
price: data.market_info.token_price,
|
|
109
|
+
priceUsd: data.market_info.price_usd,
|
|
110
|
+
holders: data.market_info.holder_count,
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
catch (error) {
|
|
114
|
+
logger.warn('Failed to fetch token market info', {
|
|
115
|
+
token: tokenAddress,
|
|
116
|
+
error: error instanceof Error ? error.message : String(error)
|
|
117
|
+
});
|
|
118
|
+
return null;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Get token info directly from blockchain
|
|
123
|
+
*/
|
|
124
|
+
export async function getTokenInfoOnChain(tokenAddress) {
|
|
125
|
+
try {
|
|
126
|
+
const status = await getTokenStatus(tokenAddress);
|
|
127
|
+
return {
|
|
128
|
+
address: tokenAddress,
|
|
129
|
+
name: '',
|
|
130
|
+
symbol: '',
|
|
131
|
+
creator: '0x0000000000000000000000000000000000000000',
|
|
132
|
+
createdAt: Date.now(),
|
|
133
|
+
graduated: status.graduated,
|
|
134
|
+
progress: status.progressPercent,
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
catch (error) {
|
|
138
|
+
logger.warn('Failed to get token info on-chain', {
|
|
139
|
+
token: tokenAddress,
|
|
140
|
+
error: error instanceof Error ? error.message : String(error)
|
|
141
|
+
});
|
|
142
|
+
return null;
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Fetch recent token activity (placeholder - would need websocket or indexer)
|
|
147
|
+
*/
|
|
148
|
+
export async function fetchTokenActivity(_tokenAddress, _limit = 50) {
|
|
149
|
+
// The nad.fun API doesn't expose activity endpoint publicly
|
|
150
|
+
// This would need websocket or event indexing
|
|
151
|
+
logger.debug('Token activity fetch not available via API');
|
|
152
|
+
return [];
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* Analyze token for trading signal
|
|
156
|
+
*/
|
|
157
|
+
export async function analyzeToken(tokenAddress) {
|
|
158
|
+
const signals = [];
|
|
159
|
+
let score = 50; // Neutral start
|
|
160
|
+
// Try to get market info from API first
|
|
161
|
+
const marketInfo = await getTokenMarketInfo(tokenAddress);
|
|
162
|
+
if (marketInfo) {
|
|
163
|
+
if (marketInfo.marketType === 'DEX') {
|
|
164
|
+
signals.push('Token graduated to DEX');
|
|
165
|
+
score += 10;
|
|
166
|
+
}
|
|
167
|
+
if (marketInfo.holders > 100) {
|
|
168
|
+
signals.push(`High holder count: ${marketInfo.holders}`);
|
|
169
|
+
score += 15;
|
|
170
|
+
}
|
|
171
|
+
else if (marketInfo.holders > 20) {
|
|
172
|
+
signals.push(`Good holder count: ${marketInfo.holders}`);
|
|
173
|
+
score += 5;
|
|
174
|
+
}
|
|
175
|
+
else if (marketInfo.holders < 5) {
|
|
176
|
+
signals.push(`Low holder count: ${marketInfo.holders}`);
|
|
177
|
+
score -= 10;
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
try {
|
|
181
|
+
const status = await getTokenStatus(tokenAddress);
|
|
182
|
+
// Check graduation status
|
|
183
|
+
if (status.graduated) {
|
|
184
|
+
if (!signals.includes('Token graduated to DEX')) {
|
|
185
|
+
signals.push('Token graduated to DEX');
|
|
186
|
+
score += 10;
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
else {
|
|
190
|
+
// Check bonding curve progress
|
|
191
|
+
const progress = status.progressPercent;
|
|
192
|
+
if (progress > 80) {
|
|
193
|
+
signals.push(`High bonding curve progress: ${progress.toFixed(1)}%`);
|
|
194
|
+
score += 15;
|
|
195
|
+
}
|
|
196
|
+
else if (progress > 50) {
|
|
197
|
+
signals.push(`Moderate progress: ${progress.toFixed(1)}%`);
|
|
198
|
+
score += 5;
|
|
199
|
+
}
|
|
200
|
+
else if (progress < 20) {
|
|
201
|
+
signals.push(`Early stage: ${progress.toFixed(1)}%`);
|
|
202
|
+
score -= 5;
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
// Check if we can get quote (token is tradeable)
|
|
206
|
+
try {
|
|
207
|
+
const quote = await getAmountOut(tokenAddress, 10n ** 17n, true); // 0.1 MON
|
|
208
|
+
if (quote.amountOut > 0n) {
|
|
209
|
+
signals.push('Token is actively tradeable');
|
|
210
|
+
score += 5;
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
catch {
|
|
214
|
+
signals.push('Quote unavailable');
|
|
215
|
+
score -= 10;
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
catch (error) {
|
|
219
|
+
signals.push('Failed to analyze token on-chain');
|
|
220
|
+
score -= 20;
|
|
221
|
+
}
|
|
222
|
+
// Determine recommendation
|
|
223
|
+
let recommendation = 'hold';
|
|
224
|
+
if (score >= 70) {
|
|
225
|
+
recommendation = 'buy';
|
|
226
|
+
}
|
|
227
|
+
else if (score <= 30) {
|
|
228
|
+
recommendation = 'sell';
|
|
229
|
+
}
|
|
230
|
+
return {
|
|
231
|
+
token: tokenAddress,
|
|
232
|
+
score,
|
|
233
|
+
signals,
|
|
234
|
+
recommendation,
|
|
235
|
+
marketInfo,
|
|
236
|
+
};
|
|
237
|
+
}
|
|
238
|
+
/**
|
|
239
|
+
* Fetch tokens from on-chain events (fallback when API unavailable)
|
|
240
|
+
*/
|
|
241
|
+
export async function fetchTokensFromChain(limit = 10) {
|
|
242
|
+
const publicClient = getPublicClient();
|
|
243
|
+
const tokens = [];
|
|
244
|
+
try {
|
|
245
|
+
// Get recent TokenCreated events from BondingCurve
|
|
246
|
+
// RPC limits to 100 blocks per request
|
|
247
|
+
const currentBlock = await publicClient.getBlockNumber();
|
|
248
|
+
const batchSize = 99n; // Stay under 100 block limit
|
|
249
|
+
const batches = 10; // Scan last 10 batches = 990 blocks
|
|
250
|
+
for (let i = 0; i < batches && tokens.length < limit; i++) {
|
|
251
|
+
const toBlock = currentBlock - (BigInt(i) * batchSize);
|
|
252
|
+
const fromBlock = toBlock - batchSize;
|
|
253
|
+
if (fromBlock < 0n)
|
|
254
|
+
break;
|
|
255
|
+
try {
|
|
256
|
+
const logs = await publicClient.getLogs({
|
|
257
|
+
address: NADFUN_CONTRACTS.BONDING_CURVE,
|
|
258
|
+
event: parseAbiItem('event Create(address indexed token, address indexed creator, uint256 virtualMon, uint256 virtualToken)'),
|
|
259
|
+
fromBlock,
|
|
260
|
+
toBlock,
|
|
261
|
+
});
|
|
262
|
+
// Process logs into tokens
|
|
263
|
+
for (const log of logs) {
|
|
264
|
+
if (tokens.length >= limit)
|
|
265
|
+
break;
|
|
266
|
+
const tokenAddress = log.args.token;
|
|
267
|
+
const creator = log.args.creator;
|
|
268
|
+
try {
|
|
269
|
+
const status = await getTokenStatus(tokenAddress);
|
|
270
|
+
tokens.push({
|
|
271
|
+
address: tokenAddress,
|
|
272
|
+
name: '',
|
|
273
|
+
symbol: '',
|
|
274
|
+
creator,
|
|
275
|
+
createdAt: Date.now(),
|
|
276
|
+
graduated: status.graduated,
|
|
277
|
+
progress: status.progressPercent,
|
|
278
|
+
});
|
|
279
|
+
}
|
|
280
|
+
catch {
|
|
281
|
+
// Token may not exist anymore
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
catch (batchError) {
|
|
286
|
+
// Log and continue to next batch
|
|
287
|
+
logger.debug('Batch scan failed', { batch: i });
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
logger.info('Fetched tokens from chain', { count: tokens.length });
|
|
291
|
+
}
|
|
292
|
+
catch (error) {
|
|
293
|
+
logger.warn('Failed to fetch tokens from chain', {
|
|
294
|
+
error: error instanceof Error ? error.message : String(error)
|
|
295
|
+
});
|
|
296
|
+
}
|
|
297
|
+
return tokens;
|
|
298
|
+
}
|
|
299
|
+
/**
|
|
300
|
+
* Scan for live trading opportunities
|
|
301
|
+
*/
|
|
302
|
+
export async function scanLiveOpportunities() {
|
|
303
|
+
const opportunities = [];
|
|
304
|
+
// Try to get tokens from API first (by volume = trending)
|
|
305
|
+
let tokens = await fetchTrendingTokens(10);
|
|
306
|
+
// If API fails, try new tokens
|
|
307
|
+
if (tokens.length === 0) {
|
|
308
|
+
tokens = await fetchNewTokens(10);
|
|
309
|
+
}
|
|
310
|
+
// If still no tokens, fetch from on-chain events
|
|
311
|
+
if (tokens.length === 0) {
|
|
312
|
+
logger.info('No API data, scanning blockchain for tokens...');
|
|
313
|
+
tokens = await fetchTokensFromChain(10);
|
|
314
|
+
}
|
|
315
|
+
// Analyze each token
|
|
316
|
+
for (const token of tokens) {
|
|
317
|
+
try {
|
|
318
|
+
const analysis = await analyzeToken(token.address);
|
|
319
|
+
opportunities.push({ token, analysis });
|
|
320
|
+
}
|
|
321
|
+
catch (error) {
|
|
322
|
+
logger.warn('Failed to analyze token', {
|
|
323
|
+
token: token.address,
|
|
324
|
+
error: error instanceof Error ? error.message : String(error)
|
|
325
|
+
});
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
// Sort by score
|
|
329
|
+
opportunities.sort((a, b) => b.analysis.score - a.analysis.score);
|
|
330
|
+
logger.info('Live scan complete', {
|
|
331
|
+
scanned: tokens.length,
|
|
332
|
+
opportunities: opportunities.filter(o => o.analysis.recommendation === 'buy').length,
|
|
333
|
+
});
|
|
334
|
+
return opportunities;
|
|
335
|
+
}
|
|
336
|
+
/**
|
|
337
|
+
* Get wallet token holdings
|
|
338
|
+
*/
|
|
339
|
+
export async function getWalletTokens(_walletAddress) {
|
|
340
|
+
// This would require indexing or API support
|
|
341
|
+
// For now return empty - would need to integrate with a token indexer
|
|
342
|
+
logger.debug('Token holdings query not yet implemented');
|
|
343
|
+
return [];
|
|
344
|
+
}
|
|
345
|
+
//# sourceMappingURL=live-scanner.js.map
|