@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.
- package/README.md +60 -39
- package/dist/analysis/formatOutput.d.ts +113 -2
- package/dist/analysis/formatOutput.js +135 -100
- package/dist/analysis/formatOutput.js.map +1 -1
- package/dist/analysis/riskScorer.d.ts +24 -2
- package/dist/analysis/riskScorer.js +146 -48
- package/dist/analysis/riskScorer.js.map +1 -1
- package/dist/analysis/summaryGenerator.d.ts +3 -2
- package/dist/analysis/summaryGenerator.js +125 -42
- package/dist/analysis/summaryGenerator.js.map +1 -1
- package/dist/cache/memoryCache.d.ts +12 -3
- package/dist/cache/memoryCache.js +43 -2
- package/dist/cache/memoryCache.js.map +1 -1
- package/dist/server.d.ts +3 -2
- package/dist/server.js +28 -16
- package/dist/server.js.map +1 -1
- package/dist/sources/dexscreener.d.ts +6 -17
- package/dist/sources/dexscreener.js +72 -26
- package/dist/sources/dexscreener.js.map +1 -1
- package/dist/sources/gmgn.d.ts +11 -4
- package/dist/sources/gmgn.js +179 -105
- package/dist/sources/gmgn.js.map +1 -1
- package/dist/sources/solanaRpc.d.ts +4 -4
- package/dist/sources/solanaRpc.js +60 -29
- package/dist/sources/solanaRpc.js.map +1 -1
- package/dist/tools/analyzeToken.d.ts +1 -2
- package/dist/tools/analyzeToken.js +114 -100
- package/dist/tools/analyzeToken.js.map +1 -1
- package/dist/tools/getPrice.d.ts +2 -12
- package/dist/tools/getPrice.js +23 -4
- package/dist/tools/getPrice.js.map +1 -1
- package/dist/tools/getTopTraders.d.ts +30 -24
- package/dist/tools/getTopTraders.js +36 -21
- package/dist/tools/getTopTraders.js.map +1 -1
- package/dist/tools/getTrending.d.ts +8 -1
- package/dist/tools/getTrending.js +12 -2
- package/dist/tools/getTrending.js.map +1 -1
- package/dist/types/index.d.ts +34 -0
- package/package.json +18 -2
package/dist/tools/getPrice.js
CHANGED
|
@@ -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
|
|
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
|
|
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
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
7
|
-
|
|
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:
|
|
38
|
-
losingCount:
|
|
52
|
+
profitableCount: profitable.length,
|
|
53
|
+
losingCount: losing.length,
|
|
39
54
|
},
|
|
40
|
-
topWinners: winners.map(
|
|
41
|
-
topLosers: losers.map(
|
|
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":"AAAA;;;GAGG;AACH,OAAO,KAAK,IAAI,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"getTopTraders.js","sourceRoot":"","sources":["../../src/tools/getTopTraders.ts"],"names":[],"mappings":"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"}
|
|
@@ -4,6 +4,13 @@ export declare function handleGetTrending(args: {
|
|
|
4
4
|
}): Promise<{
|
|
5
5
|
chain: string;
|
|
6
6
|
count: number;
|
|
7
|
-
tokens:
|
|
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
|
|
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"}
|
package/dist/types/index.d.ts
CHANGED
|
@@ -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.
|
|
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
|
}
|