@0xprotovox/deficlaw 0.1.1 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. package/README.md +60 -39
  2. package/dist/analysis/formatOutput.d.ts +113 -2
  3. package/dist/analysis/formatOutput.js +135 -100
  4. package/dist/analysis/formatOutput.js.map +1 -1
  5. package/dist/analysis/riskScorer.d.ts +24 -2
  6. package/dist/analysis/riskScorer.js +146 -48
  7. package/dist/analysis/riskScorer.js.map +1 -1
  8. package/dist/analysis/summaryGenerator.d.ts +3 -2
  9. package/dist/analysis/summaryGenerator.js +125 -42
  10. package/dist/analysis/summaryGenerator.js.map +1 -1
  11. package/dist/cache/memoryCache.d.ts +12 -3
  12. package/dist/cache/memoryCache.js +43 -2
  13. package/dist/cache/memoryCache.js.map +1 -1
  14. package/dist/server.d.ts +3 -2
  15. package/dist/server.js +28 -16
  16. package/dist/server.js.map +1 -1
  17. package/dist/sources/dexscreener.d.ts +6 -17
  18. package/dist/sources/dexscreener.js +72 -26
  19. package/dist/sources/dexscreener.js.map +1 -1
  20. package/dist/sources/gmgn.d.ts +11 -4
  21. package/dist/sources/gmgn.js +179 -105
  22. package/dist/sources/gmgn.js.map +1 -1
  23. package/dist/sources/solanaRpc.d.ts +4 -4
  24. package/dist/sources/solanaRpc.js +60 -29
  25. package/dist/sources/solanaRpc.js.map +1 -1
  26. package/dist/tools/analyzeToken.d.ts +1 -2
  27. package/dist/tools/analyzeToken.js +114 -100
  28. package/dist/tools/analyzeToken.js.map +1 -1
  29. package/dist/tools/getPrice.d.ts +2 -12
  30. package/dist/tools/getPrice.js +23 -4
  31. package/dist/tools/getPrice.js.map +1 -1
  32. package/dist/tools/getTopTraders.d.ts +30 -24
  33. package/dist/tools/getTopTraders.js +36 -21
  34. package/dist/tools/getTopTraders.js.map +1 -1
  35. package/dist/tools/getTrending.d.ts +8 -1
  36. package/dist/tools/getTrending.js +12 -2
  37. package/dist/tools/getTrending.js.map +1 -1
  38. package/dist/types/index.d.ts +34 -0
  39. package/package.json +18 -2
@@ -1,12 +1,31 @@
1
1
  /**
2
- * get_price tool — Quick price lookup
2
+ * get_price tool — Quick price lookup via DexScreener.
3
+ * Returns structured price data or error if token not found.
3
4
  */
4
- import { getPrice } from '../sources/dexscreener.js';
5
+ import { getPrice, searchTokens } from '../sources/dexscreener.js';
5
6
  export async function handleGetPrice(args) {
7
+ if (!args.token || args.token.trim().length === 0) {
8
+ return { error: 'Token address or search query is required' };
9
+ }
6
10
  const chain = args.chain || 'solana';
7
- const result = await getPrice(args.token, chain);
11
+ const token = args.token.trim();
12
+ // If it looks like an address (long alphanumeric), do direct lookup
13
+ if (token.length > 20) {
14
+ const result = await getPrice(token, chain);
15
+ if (!result) {
16
+ return { error: `Token not found: ${token} on ${chain}. Verify the address is correct.` };
17
+ }
18
+ return result;
19
+ }
20
+ // Otherwise try as a search query (symbol or name)
21
+ const pairs = await searchTokens(token);
22
+ const chainPair = pairs.find(p => p.chainId === chain) ?? pairs[0];
23
+ if (!chainPair) {
24
+ return { error: `No token found matching "${token}" on ${chain}` };
25
+ }
26
+ const result = await getPrice(chainPair.baseToken.address, chainPair.chainId);
8
27
  if (!result) {
9
- return { error: `Token not found: ${args.token} on ${chain}` };
28
+ return { error: `Token data unavailable for "${token}" on ${chain}` };
10
29
  }
11
30
  return result;
12
31
  }
@@ -1 +1 @@
1
- {"version":3,"file":"getPrice.js","sourceRoot":"","sources":["../../src/tools/getPrice.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,EAAE,QAAQ,EAAE,MAAM,2BAA2B,CAAC;AAErD,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,IAAuC;IAC1E,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,IAAI,QAAQ,CAAC;IACrC,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;IAEjD,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,OAAO,EAAE,KAAK,EAAE,oBAAoB,IAAI,CAAC,KAAK,OAAO,KAAK,EAAE,EAAE,CAAC;IACjE,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC"}
1
+ {"version":3,"file":"getPrice.js","sourceRoot":"","sources":["../../src/tools/getPrice.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAGnE,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,IAAuC;IAC1E,IAAI,CAAC,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAClD,OAAO,EAAE,KAAK,EAAE,2CAA2C,EAAE,CAAC;IAChE,CAAC;IAED,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,IAAI,QAAQ,CAAC;IACrC,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;IAEhC,oEAAoE;IACpE,IAAI,KAAK,CAAC,MAAM,GAAG,EAAE,EAAE,CAAC;QACtB,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;QAC5C,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,OAAO,EAAE,KAAK,EAAE,oBAAoB,KAAK,OAAO,KAAK,kCAAkC,EAAE,CAAC;QAC5F,CAAC;QACD,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,mDAAmD;IACnD,MAAM,KAAK,GAAG,MAAM,YAAY,CAAC,KAAK,CAAC,CAAC;IACxC,MAAM,SAAS,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,KAAK,KAAK,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC;IACnE,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,OAAO,EAAE,KAAK,EAAE,4BAA4B,KAAK,QAAQ,KAAK,EAAE,EAAE,CAAC;IACrE,CAAC;IAED,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,SAAS,CAAC,SAAS,CAAC,OAAO,EAAE,SAAS,CAAC,OAAO,CAAC,CAAC;IAC9E,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,OAAO,EAAE,KAAK,EAAE,+BAA+B,KAAK,QAAQ,KAAK,EAAE,EAAE,CAAC;IACxE,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC"}
@@ -1,3 +1,15 @@
1
+ interface TraderInfo {
2
+ address: string;
3
+ pnl: number;
4
+ profitMultiple: number;
5
+ tags: string[];
6
+ twitterHandle: string | null;
7
+ buyTx: number;
8
+ sellTx: number;
9
+ stillHolding: boolean;
10
+ isDeployer: boolean;
11
+ isDiamondHands: boolean;
12
+ }
1
13
  export declare function handleGetTopTraders(args: {
2
14
  address: string;
3
15
  limit?: number;
@@ -5,9 +17,23 @@ export declare function handleGetTopTraders(args: {
5
17
  error: string;
6
18
  token?: undefined;
7
19
  totalHoldersAnalyzed?: undefined;
20
+ note?: undefined;
8
21
  profitSummary?: undefined;
9
22
  topWinners?: undefined;
10
23
  topLosers?: undefined;
24
+ } | {
25
+ token: string;
26
+ totalHoldersAnalyzed: number;
27
+ note: string;
28
+ profitSummary: {
29
+ totalProfit: number;
30
+ totalLoss: number;
31
+ profitableCount: number;
32
+ losingCount: number;
33
+ };
34
+ topWinners: never[];
35
+ topLosers: never[];
36
+ error?: undefined;
11
37
  } | {
12
38
  token: string;
13
39
  totalHoldersAnalyzed: number;
@@ -17,29 +43,9 @@ export declare function handleGetTopTraders(args: {
17
43
  profitableCount: number;
18
44
  losingCount: number;
19
45
  };
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
- }[];
46
+ topWinners: TraderInfo[];
47
+ topLosers: TraderInfo[];
44
48
  error?: undefined;
49
+ note?: undefined;
45
50
  }>;
51
+ export {};
@@ -1,22 +1,10 @@
1
1
  /**
2
- * get_top_traders tool — Who made/lost money on a token
3
- * Uses GMGN holder data already collected by analyze_token
2
+ * get_top_traders tool — Who made/lost money on a token.
3
+ * Uses GMGN holder data to rank traders by PnL.
4
4
  */
5
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) => ({
6
+ function formatTrader(h) {
7
+ return {
20
8
  address: h.address,
21
9
  pnl: Math.round(h.totalPnl * 100) / 100,
22
10
  profitMultiple: Math.round(h.profitMultiple * 100) / 100,
@@ -27,18 +15,45 @@ export async function handleGetTopTraders(args) {
27
15
  stillHolding: h.balance > 0,
28
16
  isDeployer: h.isDeployer,
29
17
  isDiamondHands: h.tags.some(t => /diamond/i.test(t)),
30
- });
18
+ };
19
+ }
20
+ export async function handleGetTopTraders(args) {
21
+ if (!args.address || args.address.trim().length === 0) {
22
+ return { error: 'Token address is required' };
23
+ }
24
+ const limit = Math.min(Math.max(1, args.limit || 10), 50);
25
+ const { holders } = await gmgn.getHolders(args.address);
26
+ if (holders.length === 0) {
27
+ return { error: `No holder data found for ${args.address}. The token may not be indexed by GMGN.` };
28
+ }
29
+ const withPnl = holders.filter(h => h.totalPnl !== 0);
30
+ if (withPnl.length === 0) {
31
+ return {
32
+ token: args.address,
33
+ totalHoldersAnalyzed: holders.length,
34
+ note: 'No PnL data available for any holders. All holders may have entered at the same price.',
35
+ profitSummary: { totalProfit: 0, totalLoss: 0, profitableCount: 0, losingCount: 0 },
36
+ topWinners: [],
37
+ topLosers: [],
38
+ };
39
+ }
40
+ const winners = [...withPnl].sort((a, b) => b.totalPnl - a.totalPnl).slice(0, limit);
41
+ const losers = [...withPnl].sort((a, b) => a.totalPnl - b.totalPnl).slice(0, limit);
42
+ const profitable = withPnl.filter(h => h.totalPnl > 0);
43
+ const losing = withPnl.filter(h => h.totalPnl < 0);
44
+ const totalProfit = profitable.reduce((s, h) => s + h.totalPnl, 0);
45
+ const totalLoss = losing.reduce((s, h) => s + h.totalPnl, 0);
31
46
  return {
32
47
  token: args.address,
33
48
  totalHoldersAnalyzed: holders.length,
34
49
  profitSummary: {
35
50
  totalProfit: Math.round(totalProfit),
36
51
  totalLoss: Math.round(totalLoss),
37
- profitableCount: withPnl.filter(h => h.totalPnl > 0).length,
38
- losingCount: withPnl.filter(h => h.totalPnl < 0).length,
52
+ profitableCount: profitable.length,
53
+ losingCount: losing.length,
39
54
  },
40
- topWinners: winners.map(format),
41
- topLosers: losers.map(format),
55
+ topWinners: winners.map(formatTrader),
56
+ topLosers: losers.map(formatTrader),
42
57
  };
43
58
  }
44
59
  //# sourceMappingURL=getTopTraders.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"getTopTraders.js","sourceRoot":"","sources":["../../src/tools/getTopTraders.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"getTopTraders.js","sourceRoot":"","sources":["../../src/tools/getTopTraders.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,KAAK,IAAI,MAAM,oBAAoB,CAAC;AAgB3C,SAAS,YAAY,CAAC,CAAS;IAC7B,OAAO;QACL,OAAO,EAAE,CAAC,CAAC,OAAO;QAClB,GAAG,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,QAAQ,GAAG,GAAG,CAAC,GAAG,GAAG;QACvC,cAAc,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,cAAc,GAAG,GAAG,CAAC,GAAG,GAAG;QACxD,IAAI,EAAE,CAAC,CAAC,IAAI;QACZ,aAAa,EAAE,CAAC,CAAC,aAAa;QAC9B,KAAK,EAAE,CAAC,CAAC,UAAU;QACnB,MAAM,EAAE,CAAC,CAAC,WAAW;QACrB,YAAY,EAAE,CAAC,CAAC,OAAO,GAAG,CAAC;QAC3B,UAAU,EAAE,CAAC,CAAC,UAAU;QACxB,cAAc,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;KACrD,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,mBAAmB,CAAC,IAAyC;IACjF,IAAI,CAAC,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACtD,OAAO,EAAE,KAAK,EAAE,2BAA2B,EAAE,CAAC;IAChD,CAAC;IAED,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,IAAI,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;IAE1D,MAAM,EAAE,OAAO,EAAE,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAExD,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACzB,OAAO,EAAE,KAAK,EAAE,4BAA4B,IAAI,CAAC,OAAO,yCAAyC,EAAE,CAAC;IACtG,CAAC;IAED,MAAM,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,CAAC,CAAC,CAAC;IAEtD,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACzB,OAAO;YACL,KAAK,EAAE,IAAI,CAAC,OAAO;YACnB,oBAAoB,EAAE,OAAO,CAAC,MAAM;YACpC,IAAI,EAAE,wFAAwF;YAC9F,aAAa,EAAE,EAAE,WAAW,EAAE,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE,eAAe,EAAE,CAAC,EAAE,WAAW,EAAE,CAAC,EAAE;YACnF,UAAU,EAAE,EAAE;YACd,SAAS,EAAE,EAAE;SACd,CAAC;IACJ,CAAC;IAED,MAAM,OAAO,GAAG,CAAC,GAAG,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,GAAG,CAAC,CAAC,QAAQ,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;IACrF,MAAM,MAAM,GAAG,CAAC,GAAG,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,GAAG,CAAC,CAAC,QAAQ,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;IAEpF,MAAM,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,GAAG,CAAC,CAAC,CAAC;IACvD,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,GAAG,CAAC,CAAC,CAAC;IACnD,MAAM,WAAW,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC;IACnE,MAAM,SAAS,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC;IAE7D,OAAO;QACL,KAAK,EAAE,IAAI,CAAC,OAAO;QACnB,oBAAoB,EAAE,OAAO,CAAC,MAAM;QACpC,aAAa,EAAE;YACb,WAAW,EAAE,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC;YACpC,SAAS,EAAE,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC;YAChC,eAAe,EAAE,UAAU,CAAC,MAAM;YAClC,WAAW,EAAE,MAAM,CAAC,MAAM;SAC3B;QACD,UAAU,EAAE,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC;QACrC,SAAS,EAAE,MAAM,CAAC,GAAG,CAAC,YAAY,CAAC;KACpC,CAAC;AACJ,CAAC"}
@@ -4,6 +4,13 @@ export declare function handleGetTrending(args: {
4
4
  }): Promise<{
5
5
  chain: string;
6
6
  count: number;
7
- tokens: any[];
7
+ tokens: never[];
8
+ note: string;
8
9
  fetchedAt: string;
10
+ } | {
11
+ chain: string;
12
+ count: number;
13
+ tokens: (import("../types/index.js").TrendingToken & Partial<import("../types/index.js").PriceResult>)[];
14
+ fetchedAt: string;
15
+ note?: undefined;
9
16
  }>;
@@ -1,11 +1,21 @@
1
1
  /**
2
- * get_trending tool — Trending/boosted tokens
2
+ * get_trending tool — Trending/boosted tokens from DexScreener.
3
+ * Returns tokens sorted by boost activity with price enrichment.
3
4
  */
4
5
  import { getTrending } from '../sources/dexscreener.js';
5
6
  export async function handleGetTrending(args) {
6
7
  const chain = args.chain || 'solana';
7
- const limit = args.limit || 20;
8
+ const limit = Math.min(Math.max(1, args.limit || 20), 50);
8
9
  const tokens = await getTrending(chain, limit);
10
+ if (tokens.length === 0) {
11
+ return {
12
+ chain,
13
+ count: 0,
14
+ tokens: [],
15
+ note: `No trending tokens found on ${chain}. DexScreener boost data may be temporarily unavailable.`,
16
+ fetchedAt: new Date().toISOString(),
17
+ };
18
+ }
9
19
  return {
10
20
  chain,
11
21
  count: tokens.length,
@@ -1 +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"}
1
+ {"version":3,"file":"getTrending.js","sourceRoot":"","sources":["../../src/tools/getTrending.ts"],"names":[],"mappings":"AAAA;;;GAGG;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,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,IAAI,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;IAC1D,MAAM,MAAM,GAAG,MAAM,WAAW,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;IAE/C,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACxB,OAAO;YACL,KAAK;YACL,KAAK,EAAE,CAAC;YACR,MAAM,EAAE,EAAE;YACV,IAAI,EAAE,+BAA+B,KAAK,0DAA0D;YACpG,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;SACpC,CAAC;IACJ,CAAC;IAED,OAAO;QACL,KAAK;QACL,KAAK,EAAE,MAAM,CAAC,MAAM;QACpB,MAAM;QACN,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;KACpC,CAAC;AACJ,CAAC"}
@@ -1,3 +1,4 @@
1
+ /** DexScreener pair data from /latest/dex/tokens endpoint */
1
2
  export interface DexPair {
2
3
  chainId: string;
3
4
  dexId: string;
@@ -45,6 +46,37 @@ export interface DexPair {
45
46
  };
46
47
  pairCreatedAt?: number;
47
48
  }
49
+ /** Normalized price result from DexScreener */
50
+ export interface PriceResult {
51
+ address: string;
52
+ symbol: string;
53
+ name: string;
54
+ priceUsd: number;
55
+ priceChange1h: number;
56
+ priceChange24h: number;
57
+ volume24h: number;
58
+ liquidity: number;
59
+ marketCap: number;
60
+ dex: string;
61
+ }
62
+ /** Boosted/trending token from DexScreener */
63
+ export interface TrendingToken {
64
+ address: string;
65
+ symbol: string;
66
+ name: string;
67
+ chainId: string;
68
+ url: string;
69
+ boostAmount: number;
70
+ }
71
+ /** Raw GMGN boost entry from /token-boosts endpoints */
72
+ export interface DexBoostEntry {
73
+ tokenAddress?: string;
74
+ chainId?: string;
75
+ description?: string;
76
+ url?: string;
77
+ totalAmount?: number;
78
+ }
79
+ /** Normalized holder from GMGN API */
48
80
  export interface Holder {
49
81
  address: string;
50
82
  tags: string[];
@@ -68,6 +100,7 @@ export interface Holder {
68
100
  isFreshWallet: boolean;
69
101
  lastActiveAt: string | null;
70
102
  }
103
+ /** Individual risk flag from analysis */
71
104
  export interface RiskFlag {
72
105
  type: string;
73
106
  severity: 'low' | 'medium' | 'high' | 'critical';
@@ -79,6 +112,7 @@ export interface RiskAssessment {
79
112
  flags: RiskFlag[];
80
113
  summary: string;
81
114
  }
115
+ /** Complete token analysis result */
82
116
  export interface TokenAnalysis {
83
117
  token: {
84
118
  address: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@0xprotovox/deficlaw",
3
- "version": "0.1.1",
3
+ "version": "0.2.0",
4
4
  "description": "DeFi MCP Server for Claude Code — token analysis, prices, trending, holder intelligence",
5
5
  "author": "0xprotovox",
6
6
  "license": "MIT",
@@ -9,6 +9,19 @@
9
9
  "deficlaw": "dist/index.js"
10
10
  },
11
11
  "main": "dist/server.js",
12
+ "types": "dist/server.d.ts",
13
+ "files": [
14
+ "dist",
15
+ "README.md"
16
+ ],
17
+ "repository": {
18
+ "type": "git",
19
+ "url": "https://github.com/0xprotovox/deficlaw.git"
20
+ },
21
+ "bugs": {
22
+ "url": "https://github.com/0xprotovox/deficlaw/issues"
23
+ },
24
+ "homepage": "https://github.com/0xprotovox/deficlaw#readme",
12
25
  "scripts": {
13
26
  "build": "tsc",
14
27
  "start": "node dist/index.js",
@@ -41,6 +54,9 @@
41
54
  "crypto",
42
55
  "token-analysis",
43
56
  "claude-code",
44
- "ai-tools"
57
+ "ai-tools",
58
+ "dexscreener",
59
+ "gmgn",
60
+ "risk-scoring"
45
61
  ]
46
62
  }