cryptoshield 0.2.0__py3-none-any.whl

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.
cryptoshield/solana.py ADDED
@@ -0,0 +1,264 @@
1
+ """Solana token security checker.
2
+
3
+ Uses Solana RPC + Jupiter API for token data.
4
+ """
5
+
6
+ import requests
7
+ from .db import cache_get, cache_set
8
+ from .utils import print_header, print_ok, print_warn, print_fail, print_info
9
+
10
+ SOLANA_RPC = "https://api.mainnet-beta.solana.com"
11
+ JUPITER_TOKEN_API = "https://tokens.jup.ag/token/{mint}"
12
+ JUPITER_LIST = "https://tokens.jup.ag/strict"
13
+ BIRDEYE_TOKEN = "https://public-api.birdeye.so/defi/token_overview?address={mint}"
14
+
15
+
16
+ def check_solana_token(mint: str) -> dict:
17
+ """Check a Solana SPL token for security issues."""
18
+ cache_key = f"solana_token:{mint}"
19
+ cached = cache_get(cache_key)
20
+ if cached:
21
+ return cached
22
+
23
+ report = {
24
+ "mint": mint,
25
+ "chain": "solana",
26
+ "token_name": "Unknown",
27
+ "token_symbol": "?",
28
+ "risks": [],
29
+ "risk_score": 0,
30
+ "holder_count": 0,
31
+ "total_supply": 0,
32
+ "decimals": 0,
33
+ "is_on_jupiter": False,
34
+ "freeze_authority": None,
35
+ "mint_authority": None,
36
+ "is_mutable": True,
37
+ }
38
+
39
+ # 1. Get token metadata from Jupiter
40
+ try:
41
+ r = requests.get(JUPITER_TOKEN_API.format(mint=mint), timeout=10)
42
+ if r.status_code == 200:
43
+ data = r.json()
44
+ report["token_name"] = data.get("name", "Unknown")
45
+ report["token_symbol"] = data.get("symbol", "?")
46
+ report["decimals"] = data.get("decimals", 0)
47
+ report["is_on_jupiter"] = True
48
+ report["daily_volume"] = data.get("daily_volume", 0)
49
+ except Exception:
50
+ pass
51
+
52
+ # 2. Check if on Jupiter strict list (vetted tokens)
53
+ try:
54
+ r = requests.get(JUPITER_LIST, timeout=10)
55
+ if r.status_code == 200:
56
+ strict_tokens = {t["address"] for t in r.json()}
57
+ report["is_on_jupiter_strict"] = mint in strict_tokens
58
+ except Exception:
59
+ report["is_on_jupiter_strict"] = False
60
+
61
+ # 3. Get on-chain token info via RPC
62
+ try:
63
+ payload = {
64
+ "jsonrpc": "2.0",
65
+ "id": 1,
66
+ "method": "getAccountInfo",
67
+ "params": [mint, {"encoding": "jsonParsed"}],
68
+ }
69
+ r = requests.post(SOLANA_RPC, json=payload, timeout=10)
70
+ data = r.json()
71
+ account = data.get("result", {}).get("value", {})
72
+
73
+ if account:
74
+ parsed = account.get("data", {}).get("parsed", {})
75
+ info = parsed.get("info", {})
76
+
77
+ report["mint_authority"] = info.get("mintAuthority")
78
+ report["freeze_authority"] = info.get("freezeAuthority")
79
+ report["is_mutable"] = info.get("isInitialized", True)
80
+ report["total_supply"] = int(info.get("supply", "0"))
81
+ report["decimals"] = info.get("decimals", report["decimals"])
82
+ except Exception:
83
+ pass
84
+
85
+ # 4. Get holder count from Birdeye (optional, may fail without API key)
86
+ try:
87
+ headers = {"X-API-KEY": "public"}
88
+ r = requests.get(
89
+ BIRDEYE_TOKEN.format(mint=mint),
90
+ headers=headers,
91
+ timeout=10,
92
+ )
93
+ if r.status_code == 200:
94
+ birddata = r.json().get("data", {})
95
+ report["holder_count"] = birddata.get("holder", 0)
96
+ report["daily_volume"] = birddata.get("v24hUSD", report.get("daily_volume", 0))
97
+ report["market_cap"] = birddata.get("mc", 0)
98
+ report["price"] = birddata.get("price", 0)
99
+ except Exception:
100
+ pass
101
+
102
+ # Risk analysis
103
+ risks = report["risks"]
104
+ score = 0
105
+
106
+ # Freeze authority
107
+ if report["freeze_authority"]:
108
+ risks.append("FREEZE AUTHORITY — issuer can freeze your tokens")
109
+ score += 20
110
+
111
+ # Mint authority
112
+ if report["mint_authority"]:
113
+ risks.append("MINT AUTHORITY — unlimited supply, issuer can mint more")
114
+ score += 15
115
+
116
+ # Not on Jupiter
117
+ if not report["is_on_jupiter"]:
118
+ risks.append("NOT ON JUPITER — unvetted token, high risk")
119
+ score += 15
120
+
121
+ # Not on Jupiter strict list
122
+ if not report.get("is_on_jupiter_strict"):
123
+ risks.append("NOT ON JUPITER STRICT LIST — not officially vetted")
124
+ score += 5
125
+
126
+ # Low holder count
127
+ if report["holder_count"] > 0 and report["holder_count"] < 100:
128
+ risks.append(f"LOW HOLDER COUNT — only {report['holder_count']} holders")
129
+ score += 15
130
+ elif report["holder_count"] > 0 and report["holder_count"] < 1000:
131
+ risks.append(f"SMALL HOLDER COUNT — {report['holder_count']} holders")
132
+ score += 5
133
+
134
+ # Low volume
135
+ vol = report.get("daily_volume", 0)
136
+ if vol > 0 and vol < 1000:
137
+ risks.append(f"LOW VOLUME — ${vol:,.0f} in 24h")
138
+ score += 10
139
+
140
+ report["risk_score"] = min(score, 100)
141
+ if score <= 20:
142
+ report["risk_level"] = "LOW"
143
+ elif score <= 50:
144
+ report["risk_level"] = "MEDIUM"
145
+ else:
146
+ report["risk_level"] = "HIGH"
147
+
148
+ cache_set(cache_key, report, ttl=1800)
149
+ return report
150
+
151
+
152
+ def check_solana_wallet(wallet: str) -> dict:
153
+ """Check SOL balance and token holdings for a wallet."""
154
+ report = {
155
+ "wallet": wallet,
156
+ "sol_balance": 0,
157
+ "tokens": [],
158
+ }
159
+
160
+ # Get SOL balance
161
+ try:
162
+ payload = {
163
+ "jsonrpc": "2.0",
164
+ "id": 1,
165
+ "method": "getBalance",
166
+ "params": [wallet],
167
+ }
168
+ r = requests.post(SOLANA_RPC, json=payload, timeout=10)
169
+ data = r.json()
170
+ report["sol_balance"] = data.get("result", {}).get("value", 0) / 1e9
171
+ except Exception:
172
+ pass
173
+
174
+ # Get token accounts
175
+ try:
176
+ payload = {
177
+ "jsonrpc": "2.0",
178
+ "id": 1,
179
+ "method": "getTokenAccountsByOwner",
180
+ "params": [
181
+ wallet,
182
+ {"programId": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA"},
183
+ {"encoding": "jsonParsed"},
184
+ ],
185
+ }
186
+ r = requests.post(SOLANA_RPC, json=payload, timeout=10)
187
+ data = r.json()
188
+ accounts = data.get("result", {}).get("value", [])
189
+
190
+ for acc in accounts:
191
+ info = acc["account"]["data"]["parsed"]["info"]
192
+ token_amount = info.get("tokenAmount", {})
193
+ report["tokens"].append({
194
+ "mint": info.get("mint", ""),
195
+ "balance": token_amount.get("uiAmount", 0),
196
+ "decimals": token_amount.get("decimals", 0),
197
+ })
198
+ except Exception:
199
+ pass
200
+
201
+ return report
202
+
203
+
204
+ def print_solana_token_report(report: dict):
205
+ """Pretty-print Solana token check."""
206
+ name = report["token_name"]
207
+ symbol = report["token_symbol"]
208
+ print_header(f"SOLANA TOKEN CHECK — {name} ({symbol})")
209
+
210
+ # Jupiter status
211
+ if report["is_on_jupiter"]:
212
+ print_ok("Listed on Jupiter")
213
+ if report.get("is_on_jupiter_strict"):
214
+ print_ok("On Jupiter Strict List (vetted)")
215
+ else:
216
+ print_warn("NOT on Jupiter Strict List")
217
+ else:
218
+ print_fail("Not listed on Jupiter — unvetted token")
219
+
220
+ # Freeze authority
221
+ if report["freeze_authority"]:
222
+ print_fail(f"Freeze Authority: {report['freeze_authority'][:10]}...")
223
+ else:
224
+ print_ok("Freeze Authority: None")
225
+
226
+ # Mint authority
227
+ if report["mint_authority"]:
228
+ print_fail(f"Mint Authority: {report['mint_authority'][:10]}...")
229
+ else:
230
+ print_ok("Mint Authority: None (fixed supply)")
231
+
232
+ # Holders
233
+ if report["holder_count"]:
234
+ if report["holder_count"] < 100:
235
+ print_fail(f"Holders: {report['holder_count']:,}")
236
+ elif report["holder_count"] < 1000:
237
+ print_warn(f"Holders: {report['holder_count']:,}")
238
+ else:
239
+ print_ok(f"Holders: {report['holder_count']:,}")
240
+
241
+ # Volume
242
+ vol = report.get("daily_volume", 0)
243
+ if vol:
244
+ print_info(f"24h Volume: ${vol:,.0f}")
245
+
246
+ # Market cap
247
+ mc = report.get("market_cap", 0)
248
+ if mc:
249
+ print_info(f"Market Cap: ${mc:,.0f}")
250
+
251
+ # Risk score
252
+ score = report["risk_score"]
253
+ level = report.get("risk_level", "UNKNOWN")
254
+ if level == "LOW":
255
+ print_ok(f"Risk Score: {score}/100 — {level} RISK")
256
+ elif level == "MEDIUM":
257
+ print_warn(f"Risk Score: {score}/100 — {level} RISK")
258
+ else:
259
+ print_fail(f"Risk Score: {score}/100 — {level} RISK")
260
+
261
+ if report["risks"]:
262
+ print()
263
+ for risk in report["risks"]:
264
+ print(f" ⚡ {risk}")
cryptoshield/utils.py ADDED
@@ -0,0 +1,194 @@
1
+ """Shared utilities."""
2
+
3
+ import sys
4
+ from typing import Optional
5
+
6
+ import requests
7
+ from web3 import Web3
8
+
9
+ # Default RPC endpoints (public, no key needed)
10
+ RPC_ENDPOINTS = {
11
+ "eth": "https://eth.llamarpc.com",
12
+ "bsc": "https://bsc-dataseed1.binance.org",
13
+ "polygon": "https://polygon-rpc.com",
14
+ "arbitrum": "https://arb1.arbitrum.io/rpc",
15
+ "optimism": "https://mainnet.optimism.io",
16
+ "base": "https://mainnet.base.org",
17
+ "avalanche": "https://api.avax.network/ext/bc/C/rpc",
18
+ "fantom": "https://rpc.ftm.tools",
19
+ }
20
+
21
+ CHAIN_IDS = {
22
+ "eth": 1,
23
+ "bsc": 56,
24
+ "polygon": 137,
25
+ "arbitrum": 42161,
26
+ "optimism": 10,
27
+ "base": 8453,
28
+ "avalanche": 43114,
29
+ "fantom": 250,
30
+ }
31
+
32
+ # Minimal ERC-20 ABI
33
+ ERC20_ABI = [
34
+ {
35
+ "constant": True,
36
+ "inputs": [{"name": "_owner", "type": "address"}],
37
+ "name": "balanceOf",
38
+ "outputs": [{"name": "balance", "type": "uint256"}],
39
+ "type": "function",
40
+ },
41
+ {
42
+ "constant": True,
43
+ "inputs": [
44
+ {"name": "_owner", "type": "address"},
45
+ {"name": "_spender", "type": "address"},
46
+ ],
47
+ "name": "allowance",
48
+ "outputs": [{"name": "", "type": "uint256"}],
49
+ "type": "function",
50
+ },
51
+ {
52
+ "constant": True,
53
+ "inputs": [],
54
+ "name": "name",
55
+ "outputs": [{"name": "", "type": "string"}],
56
+ "type": "function",
57
+ },
58
+ {
59
+ "constant": True,
60
+ "inputs": [],
61
+ "name": "symbol",
62
+ "outputs": [{"name": "", "type": "string"}],
63
+ "type": "function",
64
+ },
65
+ {
66
+ "constant": True,
67
+ "inputs": [],
68
+ "name": "decimals",
69
+ "outputs": [{"name": "", "type": "uint8"}],
70
+ "type": "function",
71
+ },
72
+ {
73
+ "constant": True,
74
+ "inputs": [],
75
+ "name": "totalSupply",
76
+ "outputs": [{"name": "", "type": "uint256"}],
77
+ "type": "function",
78
+ },
79
+ {
80
+ "constant": False,
81
+ "inputs": [
82
+ {"name": "_spender", "type": "address"},
83
+ {"name": "_value", "type": "uint256"},
84
+ ],
85
+ "name": "approve",
86
+ "outputs": [{"name": "", "type": "bool"}],
87
+ "type": "function",
88
+ },
89
+ {
90
+ "constant": True,
91
+ "inputs": [],
92
+ "name": "owner",
93
+ "outputs": [{"name": "", "type": "address"}],
94
+ "type": "function",
95
+ },
96
+ ]
97
+
98
+ # Transfer event ABI
99
+ TRANSFER_EVENT = {
100
+ "anonymous": False,
101
+ "inputs": [
102
+ {"indexed": True, "name": "from", "type": "address"},
103
+ {"indexed": True, "name": "to", "type": "address"},
104
+ {"indexed": False, "name": "value", "type": "uint256"},
105
+ ],
106
+ "name": "Transfer",
107
+ "type": "event",
108
+ }
109
+
110
+ # Approval event ABI
111
+ APPROVAL_EVENT = {
112
+ "anonymous": False,
113
+ "inputs": [
114
+ {"indexed": True, "name": "owner", "type": "address"},
115
+ {"indexed": True, "name": "spender", "type": "address"},
116
+ {"indexed": False, "name": "value", "type": "uint256"},
117
+ ],
118
+ "name": "Approval",
119
+ "type": "event",
120
+ }
121
+
122
+ # Well-known addresses to label
123
+ KNOWN_ADDRESSES = {
124
+ "0x7a250d5630b4cf539739df2c5dacb4c659f2488d": "Uniswap V2 Router",
125
+ "0xe592427a0aece92de3edee1f18e0157c05861564": "Uniswap V3 Router",
126
+ "0x68b3465833fb72a70ecdf485e0e4c7bd8665fc45": "Uniswap SwapRouter02",
127
+ "0x1111111254fb6c44bac0bed2854e76f90643097d": "1inch Router V4",
128
+ "0xdef1c0ded9bec7f1a1670819833240f027b25eff": "0x Exchange Proxy",
129
+ "0x1111111254eeb25477b68fb85ed929f73a960582": "1inch Router V5",
130
+ "0xd9e1ce17f2641f24ae83637ab66a2cca9c378b9f": "SushiSwap Router",
131
+ "0x000000000022d473030f116ddee9f6b43ac78ba3": "Seaport (OpenSea)",
132
+ "0x3fc91a3afd70395cd496c647d5a6cc9d4b2b7fad": "Universal Router",
133
+ "0x00000000000000adc04c56bf30ac9d3c0aaf14dc": "Seaport 1.5",
134
+ "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48": "USDC",
135
+ "0xdac17f958d2ee523a2206206994597c13d831ec7": "USDT",
136
+ "0x6b175474e89094c44da98b954eedeac495271d0f": "DAI",
137
+ "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2": "WETH",
138
+ "0x2260fac5e5542a773aa44fbcfedf7c193bc2c599": "WBTC",
139
+ }
140
+
141
+
142
+ def get_web3(chain: str = "eth") -> Web3:
143
+ rpc = RPC_ENDPOINTS.get(chain)
144
+ if not rpc:
145
+ print(f"Unsupported chain: {chain}")
146
+ sys.exit(1)
147
+ return Web3(Web3.HTTPProvider(rpc))
148
+
149
+
150
+ def is_valid_address(addr: str) -> bool:
151
+ return Web3.is_address(addr)
152
+
153
+
154
+ def checksum(addr: str) -> str:
155
+ return Web3.to_checksum_address(addr)
156
+
157
+
158
+ def label_address(addr: str) -> str:
159
+ addr_lower = addr.lower()
160
+ label = KNOWN_ADDRESSES.get(addr_lower, "")
161
+ if label:
162
+ return f"{addr[:6]}...{addr[-4:]} ({label})"
163
+ return f"{addr[:6]}...{addr[-4:]}"
164
+
165
+
166
+ def fetch_json(url: str, params: Optional[dict] = None, timeout: int = 15) -> dict:
167
+ try:
168
+ r = requests.get(url, params=params, timeout=timeout)
169
+ r.raise_for_status()
170
+ return r.json()
171
+ except Exception as e:
172
+ return {"error": str(e)}
173
+
174
+
175
+ def print_header(title: str):
176
+ print(f"\n{'━' * 40}")
177
+ print(f" {title}")
178
+ print(f"{'━' * 40}")
179
+
180
+
181
+ def print_ok(msg: str):
182
+ print(f" ✅ {msg}")
183
+
184
+
185
+ def print_warn(msg: str):
186
+ print(f" âš ī¸ {msg}")
187
+
188
+
189
+ def print_fail(msg: str):
190
+ print(f" ❌ {msg}")
191
+
192
+
193
+ def print_info(msg: str):
194
+ print(f" â„šī¸ {msg}")
@@ -0,0 +1,157 @@
1
+ Metadata-Version: 2.4
2
+ Name: cryptoshield
3
+ Version: 0.2.0
4
+ Summary: All-in-one crypto security toolkit — honeypot, approvals, rugpull, phishing
5
+ Author-email: yossweh <cilokcilok15@gmail.com>
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/yossweh/cryptoshield
8
+ Project-URL: Repository, https://github.com/yossweh/cryptoshield
9
+ Project-URL: Issues, https://github.com/yossweh/cryptoshield/issues
10
+ Keywords: crypto,security,honeypot,rugpull,web3,defi,approval
11
+ Classifier: Development Status :: 4 - Beta
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: License :: OSI Approved :: MIT License
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Topic :: Security
16
+ Classifier: Topic :: Software Development :: Libraries
17
+ Requires-Python: >=3.9
18
+ Description-Content-Type: text/markdown
19
+ License-File: LICENSE
20
+ Requires-Dist: typer>=0.9.0
21
+ Requires-Dist: web3>=6.0.0
22
+ Requires-Dist: requests>=2.28.0
23
+ Dynamic: license-file
24
+
25
+ # 🛡 CryptoShield
26
+
27
+ **All-in-one crypto security toolkit.** Check tokens before you buy. Scan your wallet for dangerous approvals. Detect rugpulls. Block phishing sites.
28
+
29
+ [![Python 3.9+](https://img.shields.io/badge/python-3.9+-blue.svg)](https://python.org)
30
+ [![License: MIT](https://img.shields.io/badge/License-MIT-green.svg)](LICENSE)
31
+ [![PyPI](https://img.shields.io/pypi/v/cryptoshield.svg)](https://pypi.org/project/cryptoshield/)
32
+
33
+ ## Features
34
+
35
+ - **đŸ¯ Honeypot Detection** — Can you sell? Hidden taxes? Mint function? Check before you buy.
36
+ - **📋 Approval Scanner** — Find all token approvals on your wallet. Flag dangerous unlimited approvals.
37
+ - **🔴 Rugpull Scorer** — Analyze contracts for common rug patterns. Score 0-100.
38
+ - **đŸŽŖ Phishing Checker** — 60+ known scam domains. Typosquatting, fake airdrops, wallet drainers.
39
+ - **â˜€ī¸ Solana Support** — Check SPL tokens, freeze/mint authority, Jupiter listing status.
40
+ - **đŸ“Ļ Batch Mode** — Check 100+ tokens/wallets from a file.
41
+
42
+ ## Install
43
+
44
+ ```bash
45
+ pip install cryptoshield
46
+ ```
47
+
48
+ Or from source:
49
+
50
+ ```bash
51
+ git clone https://github.com/yossweh/cryptoshield
52
+ cd cryptoshield
53
+ pip install -e .
54
+ ```
55
+
56
+ ## Usage
57
+
58
+ ### Full security report (EVM)
59
+ ```bash
60
+ cryptoshield check 0xdAC17F958D2ee523a2206206994597C13D831ec7
61
+ cryptoshield check 0xToken --chain bsc
62
+ cryptoshield check 0xToken --quick # honeypot only
63
+ ```
64
+
65
+ ### Solana token check
66
+ ```bash
67
+ cryptoshield check EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v --chain solana
68
+ ```
69
+
70
+ ### Scan wallet approvals
71
+ ```bash
72
+ cryptoshield approvals 0xYourWallet
73
+ cryptoshield approvals 0xYourWallet --chain polygon
74
+ ```
75
+
76
+ ### Check phishing URL
77
+ ```bash
78
+ cryptoshield check-url uniswap-airdrop.com
79
+ cryptoshield check-url https://app.uniswap.org
80
+ cryptoshield check-url metamask-sync.xyz
81
+ ```
82
+
83
+ ### Solana wallet scan
84
+ ```bash
85
+ cryptoshield solana YourSolanaWalletAddress
86
+ ```
87
+
88
+ ### Batch check
89
+ ```bash
90
+ cryptoshield batch tokens.txt --mode honeypot
91
+ cryptoshield batch tokens.txt --mode honeypot --chain solana
92
+ cryptoshield batch wallets.txt --mode approvals --chain bsc
93
+ ```
94
+
95
+ ## Example Output
96
+
97
+ ```
98
+ 🛡 CRYPTO SHIELD REPORT
99
+ ━━━━━━━━━━━━━━━━━━━━━━━
100
+
101
+ đŸ¯ HONEYPOT CHECK — Tether USD (USDT)
102
+ ✅ Can sell: YES
103
+ ✅ Tax: 0% buy / 0% sell
104
+ ❌ Owner can mint: YES — infinite supply risk
105
+ ❌ Owner can change balances: YES
106
+ ✅ Contract: Verified
107
+ â„šī¸ Holders: 14,585,422
108
+ âš ī¸ Risk Score: 30/100 — MEDIUM RISK
109
+
110
+ đŸŽŖ PHISHING CHECK — uniswap-airdrop.com
111
+ 🚨 KNOWN SCAM DOMAIN — DO NOT VISIT
112
+ ❌ KNOWN SCAM DOMAIN — uniswap-airdrop.com is in scam database
113
+
114
+ â˜€ī¸ SOLANA TOKEN CHECK — SafeToken (SAFE)
115
+ ✅ Listed on Jupiter
116
+ ✅ On Jupiter Strict List (vetted)
117
+ ✅ Freeze Authority: None
118
+ ✅ Mint Authority: None (fixed supply)
119
+ ✅ Holders: 5,432
120
+ ✅ Risk Score: 0/100 — LOW RISK
121
+ ```
122
+
123
+ ## Supported Chains
124
+
125
+ | Chain | Honeypot | Approvals | Rugpull |
126
+ |-------|----------|-----------|---------|
127
+ | Ethereum | ✅ | ✅ | ✅ |
128
+ | BSC | ✅ | ✅ | ✅ |
129
+ | Polygon | ✅ | ✅ | ✅ |
130
+ | Arbitrum | ✅ | ✅ | ✅ |
131
+ | Optimism | ✅ | ✅ | ✅ |
132
+ | Base | ✅ | ✅ | ✅ |
133
+ | Avalanche | ✅ | ✅ | ✅ |
134
+ | Fantom | ✅ | ✅ | ✅ |
135
+ | Solana | ✅ | — | ✅ |
136
+
137
+ ## Data Sources
138
+
139
+ - **GoPlus Security API** — Honeypot detection, token security analysis (free, no key)
140
+ - **Jupiter API** — Solana token data, strict list
141
+ - **Birdeye API** — Solana holder count, volume
142
+ - **On-chain data** — Approval events, contract code, ownership (direct RPC)
143
+ - **Heuristics** — URL pattern matching, domain analysis, typosquatting detection
144
+ - **Community scam database** — 60+ known phishing domains
145
+
146
+ ## Contributing
147
+
148
+ PRs welcome! Especially:
149
+
150
+ - More scam domains / phishing patterns
151
+ - More chain support (TON, Sui, Aptos)
152
+ - Better rugpull heuristics
153
+ - UI improvements
154
+
155
+ ## License
156
+
157
+ MIT
@@ -0,0 +1,15 @@
1
+ cryptoshield/__init__.py,sha256=aHkk2WXVV51D4zlLYdV6GNaao5V_Z146v4kXfmBQYgc,105
2
+ cryptoshield/approvals.py,sha256=La44yNJqzTVkJt1GLJqnk4Hg099-ytNkxTO3foNc2OA,5517
3
+ cryptoshield/cli.py,sha256=c7gFg8P7ulj-oBGTfjkfwj-dhX0F59kSigmcqPiXtew,5619
4
+ cryptoshield/db.py,sha256=371XFYFgEoEhe2gbzIv2DFcNfHB8bX1bG38c1uvjXuE,1169
5
+ cryptoshield/honeypot.py,sha256=jZMOUFU5RIIXRZ-_i7zAsAjDoat-PtACd2hCm6tze8c,7486
6
+ cryptoshield/phishing.py,sha256=JgGZHo9PX00GnVN02swj3Y7XeOq0SDbrv0iu0zkodaw,12287
7
+ cryptoshield/rugpull.py,sha256=CI_FqMld6rzsfz1YIVvm5PxiOEN2a1L2MP-wyktkx0Q,5525
8
+ cryptoshield/solana.py,sha256=GuKCD9mRM4wjC4VE0nCUazyK4Wh7VP8P18keZaRB0W8,8399
9
+ cryptoshield/utils.py,sha256=CywjELqlKJmSl6KRHbLf956Ns2zpZ45AuLqe75ljKIE,5240
10
+ cryptoshield-0.2.0.dist-info/licenses/LICENSE,sha256=2P1HcJoaA_1bos2PzIXkSFjMv7JgGQDnB9Yz1MaKEiY,1064
11
+ cryptoshield-0.2.0.dist-info/METADATA,sha256=Yy6vcK-GI_gqmTLGuLQqdOyAEe6qQixW93TdUJE1E4Y,4783
12
+ cryptoshield-0.2.0.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91
13
+ cryptoshield-0.2.0.dist-info/entry_points.txt,sha256=7DOJMy4KvAZpSFkqq1Akp9GizoMwf59lj-eKethhSuI,55
14
+ cryptoshield-0.2.0.dist-info/top_level.txt,sha256=bJXUAxolMDDB1OfNQQPuxqXSU42OgIALB9H4BMB3EDc,13
15
+ cryptoshield-0.2.0.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (82.0.1)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ cryptoshield = cryptoshield.cli:main
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 yossweh
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1 @@
1
+ cryptoshield