@0xprotovox/deficlaw 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. package/README.md +230 -0
  2. package/dist/analysis/formatOutput.d.ts +4 -0
  3. package/dist/analysis/formatOutput.js +209 -0
  4. package/dist/analysis/formatOutput.js.map +1 -0
  5. package/dist/analysis/riskScorer.d.ts +6 -0
  6. package/dist/analysis/riskScorer.js +104 -0
  7. package/dist/analysis/riskScorer.js.map +1 -0
  8. package/dist/analysis/summaryGenerator.d.ts +68 -0
  9. package/dist/analysis/summaryGenerator.js +171 -0
  10. package/dist/analysis/summaryGenerator.js.map +1 -0
  11. package/dist/cache/memoryCache.d.ts +13 -0
  12. package/dist/cache/memoryCache.js +31 -0
  13. package/dist/cache/memoryCache.js.map +1 -0
  14. package/dist/index.d.ts +2 -0
  15. package/dist/index.js +12 -0
  16. package/dist/index.js.map +1 -0
  17. package/dist/server.d.ts +7 -0
  18. package/dist/server.js +76 -0
  19. package/dist/server.js.map +1 -0
  20. package/dist/sources/dexscreener.d.ts +20 -0
  21. package/dist/sources/dexscreener.js +117 -0
  22. package/dist/sources/dexscreener.js.map +1 -0
  23. package/dist/sources/gmgn.d.ts +8 -0
  24. package/dist/sources/gmgn.js +210 -0
  25. package/dist/sources/gmgn.js.map +1 -0
  26. package/dist/sources/solanaRpc.d.ts +14 -0
  27. package/dist/sources/solanaRpc.js +60 -0
  28. package/dist/sources/solanaRpc.js.map +1 -0
  29. package/dist/tools/analyzeToken.d.ts +8 -0
  30. package/dist/tools/analyzeToken.js +253 -0
  31. package/dist/tools/analyzeToken.js.map +1 -0
  32. package/dist/tools/getPrice.d.ts +17 -0
  33. package/dist/tools/getPrice.js +13 -0
  34. package/dist/tools/getPrice.js.map +1 -0
  35. package/dist/tools/getTopTraders.d.ts +45 -0
  36. package/dist/tools/getTopTraders.js +44 -0
  37. package/dist/tools/getTopTraders.js.map +1 -0
  38. package/dist/tools/getTrending.d.ts +9 -0
  39. package/dist/tools/getTrending.js +16 -0
  40. package/dist/tools/getTrending.js.map +1 -0
  41. package/dist/types/index.d.ts +127 -0
  42. package/dist/types/index.js +2 -0
  43. package/dist/types/index.js.map +1 -0
  44. package/package.json +46 -0
@@ -0,0 +1,45 @@
1
+ export declare function handleGetTopTraders(args: {
2
+ address: string;
3
+ limit?: number;
4
+ }): Promise<{
5
+ error: string;
6
+ token?: undefined;
7
+ totalHoldersAnalyzed?: undefined;
8
+ profitSummary?: undefined;
9
+ topWinners?: undefined;
10
+ topLosers?: undefined;
11
+ } | {
12
+ token: string;
13
+ totalHoldersAnalyzed: number;
14
+ profitSummary: {
15
+ totalProfit: number;
16
+ totalLoss: number;
17
+ profitableCount: number;
18
+ losingCount: number;
19
+ };
20
+ topWinners: {
21
+ address: string;
22
+ pnl: number;
23
+ profitMultiple: number;
24
+ tags: string[];
25
+ twitterHandle: string | null;
26
+ buyTx: number;
27
+ sellTx: number;
28
+ stillHolding: boolean;
29
+ isDeployer: boolean;
30
+ isDiamondHands: boolean;
31
+ }[];
32
+ topLosers: {
33
+ address: string;
34
+ pnl: number;
35
+ profitMultiple: number;
36
+ tags: string[];
37
+ twitterHandle: string | null;
38
+ buyTx: number;
39
+ sellTx: number;
40
+ stillHolding: boolean;
41
+ isDeployer: boolean;
42
+ isDiamondHands: boolean;
43
+ }[];
44
+ error?: undefined;
45
+ }>;
@@ -0,0 +1,44 @@
1
+ /**
2
+ * get_top_traders tool — Who made/lost money on a token
3
+ * Uses GMGN holder data already collected by analyze_token
4
+ */
5
+ import * as gmgn from '../sources/gmgn.js';
6
+ export async function handleGetTopTraders(args) {
7
+ const limit = args.limit || 10;
8
+ if (!(await gmgn.isPlaywrightAvailable())) {
9
+ return { error: 'Playwright not installed. Run: npm install playwright && npx playwright install chromium' };
10
+ }
11
+ const { holders } = await gmgn.getHolders(args.address);
12
+ if (holders.length === 0)
13
+ return { error: 'No holder data found' };
14
+ const withPnl = holders.filter(h => h.totalPnl !== 0);
15
+ const winners = [...withPnl].sort((a, b) => b.totalPnl - a.totalPnl).slice(0, limit);
16
+ const losers = [...withPnl].sort((a, b) => a.totalPnl - b.totalPnl).slice(0, limit);
17
+ const totalProfit = withPnl.filter(h => h.totalPnl > 0).reduce((s, h) => s + h.totalPnl, 0);
18
+ const totalLoss = withPnl.filter(h => h.totalPnl < 0).reduce((s, h) => s + h.totalPnl, 0);
19
+ const format = (h) => ({
20
+ address: h.address,
21
+ pnl: Math.round(h.totalPnl * 100) / 100,
22
+ profitMultiple: Math.round(h.profitMultiple * 100) / 100,
23
+ tags: h.tags,
24
+ twitterHandle: h.twitterHandle,
25
+ buyTx: h.buyTxCount,
26
+ sellTx: h.sellTxCount,
27
+ stillHolding: h.balance > 0,
28
+ isDeployer: h.isDeployer,
29
+ isDiamondHands: h.tags.some(t => /diamond/i.test(t)),
30
+ });
31
+ return {
32
+ token: args.address,
33
+ totalHoldersAnalyzed: holders.length,
34
+ profitSummary: {
35
+ totalProfit: Math.round(totalProfit),
36
+ totalLoss: Math.round(totalLoss),
37
+ profitableCount: withPnl.filter(h => h.totalPnl > 0).length,
38
+ losingCount: withPnl.filter(h => h.totalPnl < 0).length,
39
+ },
40
+ topWinners: winners.map(format),
41
+ topLosers: losers.map(format),
42
+ };
43
+ }
44
+ //# sourceMappingURL=getTopTraders.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"getTopTraders.js","sourceRoot":"","sources":["../../src/tools/getTopTraders.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ export declare function handleGetTrending(args: {
2
+ chain?: string;
3
+ limit?: number;
4
+ }): Promise<{
5
+ chain: string;
6
+ count: number;
7
+ tokens: any[];
8
+ fetchedAt: string;
9
+ }>;
@@ -0,0 +1,16 @@
1
+ /**
2
+ * get_trending tool — Trending/boosted tokens
3
+ */
4
+ import { getTrending } from '../sources/dexscreener.js';
5
+ export async function handleGetTrending(args) {
6
+ const chain = args.chain || 'solana';
7
+ const limit = args.limit || 20;
8
+ const tokens = await getTrending(chain, limit);
9
+ return {
10
+ chain,
11
+ count: tokens.length,
12
+ tokens,
13
+ fetchedAt: new Date().toISOString(),
14
+ };
15
+ }
16
+ //# sourceMappingURL=getTrending.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"getTrending.js","sourceRoot":"","sources":["../../src/tools/getTrending.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AAExD,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,IAAwC;IAC9E,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,IAAI,QAAQ,CAAC;IACrC,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,IAAI,EAAE,CAAC;IAC/B,MAAM,MAAM,GAAG,MAAM,WAAW,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;IAE/C,OAAO;QACL,KAAK;QACL,KAAK,EAAE,MAAM,CAAC,MAAM;QACpB,MAAM;QACN,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;KACpC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,127 @@
1
+ export interface DexPair {
2
+ chainId: string;
3
+ dexId: string;
4
+ pairAddress: string;
5
+ baseToken: {
6
+ address: string;
7
+ name: string;
8
+ symbol: string;
9
+ };
10
+ quoteToken: {
11
+ address: string;
12
+ name: string;
13
+ symbol: string;
14
+ };
15
+ priceNative: string;
16
+ priceUsd: string;
17
+ volume: {
18
+ h24: number;
19
+ h6: number;
20
+ h1: number;
21
+ m5: number;
22
+ };
23
+ priceChange: {
24
+ h24: number;
25
+ h6: number;
26
+ h1: number;
27
+ m5: number;
28
+ };
29
+ liquidity: {
30
+ usd: number;
31
+ base: number;
32
+ quote: number;
33
+ };
34
+ fdv: number;
35
+ marketCap: number;
36
+ info?: {
37
+ imageUrl?: string;
38
+ websites?: {
39
+ url: string;
40
+ }[];
41
+ socials?: {
42
+ type: string;
43
+ url: string;
44
+ }[];
45
+ };
46
+ pairCreatedAt?: number;
47
+ }
48
+ export interface Holder {
49
+ address: string;
50
+ tags: string[];
51
+ twitterHandle: string | null;
52
+ twitterName: string | null;
53
+ name: string | null;
54
+ balance: number;
55
+ supplyPercent: number;
56
+ valueUsd: number;
57
+ avgBuyPrice: number;
58
+ cost: number;
59
+ unrealizedPnl: number;
60
+ realizedPnl: number;
61
+ totalPnl: number;
62
+ profitMultiple: number;
63
+ buyAmount: number;
64
+ sellAmount: number;
65
+ buyTxCount: number;
66
+ sellTxCount: number;
67
+ isDeployer: boolean;
68
+ isFreshWallet: boolean;
69
+ lastActiveAt: string | null;
70
+ }
71
+ export interface RiskFlag {
72
+ type: string;
73
+ severity: 'low' | 'medium' | 'high' | 'critical';
74
+ message: string;
75
+ }
76
+ export interface RiskAssessment {
77
+ score: number;
78
+ level: 'LOW' | 'MEDIUM' | 'HIGH' | 'CRITICAL';
79
+ flags: RiskFlag[];
80
+ summary: string;
81
+ }
82
+ export interface TokenAnalysis {
83
+ token: {
84
+ address: string;
85
+ name: string;
86
+ symbol: string;
87
+ chain: string;
88
+ imageUrl?: string;
89
+ };
90
+ price: {
91
+ usd: number;
92
+ nativePrice: string;
93
+ change1h: number;
94
+ change24h: number;
95
+ };
96
+ market: {
97
+ marketCap: number;
98
+ fdv: number;
99
+ volume24h: number;
100
+ volume1h: number;
101
+ liquidity: number;
102
+ dex: string;
103
+ pairAddress: string;
104
+ pairCreatedAt?: string;
105
+ };
106
+ holders?: {
107
+ total: number;
108
+ top: Holder[];
109
+ devWallet: {
110
+ address: string;
111
+ holdingPercent: number;
112
+ status: string;
113
+ } | null;
114
+ distribution: {
115
+ top10Percent: number;
116
+ top20Percent: number;
117
+ freshWalletPercent: number;
118
+ sniperCount: number;
119
+ kolCount: number;
120
+ };
121
+ };
122
+ risk: RiskAssessment;
123
+ meta: {
124
+ sources: string[];
125
+ fetchTimeMs: number;
126
+ };
127
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":""}
package/package.json ADDED
@@ -0,0 +1,46 @@
1
+ {
2
+ "name": "@0xprotovox/deficlaw",
3
+ "version": "0.1.1",
4
+ "description": "DeFi MCP Server for Claude Code — token analysis, prices, trending, holder intelligence",
5
+ "author": "0xprotovox",
6
+ "license": "MIT",
7
+ "type": "module",
8
+ "bin": {
9
+ "deficlaw": "dist/index.js"
10
+ },
11
+ "main": "dist/server.js",
12
+ "scripts": {
13
+ "build": "tsc",
14
+ "start": "node dist/index.js",
15
+ "dev": "tsx src/index.ts"
16
+ },
17
+ "dependencies": {
18
+ "@modelcontextprotocol/sdk": "^1.27.1",
19
+ "zod": "^3.23.0"
20
+ },
21
+ "peerDependencies": {
22
+ "playwright": "^1.58.2"
23
+ },
24
+ "peerDependenciesMeta": {
25
+ "playwright": {
26
+ "optional": true
27
+ }
28
+ },
29
+ "devDependencies": {
30
+ "@types/node": "^22.0.0",
31
+ "tsx": "^4.19.0",
32
+ "typescript": "^5.5.0"
33
+ },
34
+ "engines": {
35
+ "node": ">=18.0.0"
36
+ },
37
+ "keywords": [
38
+ "mcp",
39
+ "defi",
40
+ "solana",
41
+ "crypto",
42
+ "token-analysis",
43
+ "claude-code",
44
+ "ai-tools"
45
+ ]
46
+ }