@intentsolutionsio/token-launch-tracker 1.0.0 → 1.0.4

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.
@@ -3,31 +3,40 @@
3
3
  ## RPC Connection Errors
4
4
 
5
5
  ### Connection Timeout
6
+
6
7
  ```
7
8
  Error: RPC connection timeout after 30s
8
9
  ```
10
+
9
11
  **Cause:** RPC endpoint is overloaded or unreachable.
10
12
  **Solution:**
13
+
11
14
  1. Try a different RPC URL with `--rpc-url`
12
15
  2. Use a backup RPC provider (Alchemy, Chainstack, Infura, or QuickNode)
13
16
  3. Reduce request frequency
14
17
 
15
18
  ### RPC Rate Limited
19
+
16
20
  ```
17
21
  Error: 429 Too Many Requests
18
22
  ```
23
+
19
24
  **Cause:** Exceeded RPC provider rate limits.
20
25
  **Solution:**
26
+
21
27
  1. Add delay between requests
22
28
  2. Upgrade to paid RPC tier
23
29
  3. Use multiple RPC endpoints with round-robin
24
30
 
25
31
  ### Invalid Chain
32
+
26
33
  ```
27
34
  Error: Unsupported chain: xyz
28
35
  ```
36
+
29
37
  **Cause:** Chain not in supported list.
30
38
  **Solution:**
39
+
31
40
  1. Use `python launch_tracker.py chains` to see supported chains
32
41
  2. Check spelling (lowercase required)
33
42
  3. Add custom chain config if needed
@@ -35,21 +44,27 @@ Error: Unsupported chain: xyz
35
44
  ## Event Parsing Errors
36
45
 
37
46
  ### No Pairs Found
47
+
38
48
  ```
39
49
  No new pairs found in the specified timeframe.
40
50
  ```
51
+
41
52
  **Cause:** No PairCreated events in time window.
42
53
  **Solution:**
54
+
43
55
  1. Extend the time window with `--hours`
44
56
  2. Check if correct chain is selected
45
57
  3. Verify DEX is active on that chain
46
58
 
47
59
  ### Log Parsing Failed
60
+
48
61
  ```
49
62
  Error parsing log: list index out of range
50
63
  ```
64
+
51
65
  **Cause:** Unexpected event format (V3 vs V2).
52
66
  **Solution:**
67
+
53
68
  1. Check DEX version compatibility
54
69
  2. Verify factory address is correct
55
70
  3. Enable `--verbose` for debugging
@@ -57,31 +72,40 @@ Error parsing log: list index out of range
57
72
  ## Contract Analysis Errors
58
73
 
59
74
  ### Bytecode Not Found
75
+
60
76
  ```
61
77
  Error: Contract has no bytecode
62
78
  ```
79
+
63
80
  **Cause:** Address is not a contract (EOA) or wrong network.
64
81
  **Solution:**
82
+
65
83
  1. Verify address is a contract
66
84
  2. Check correct chain is selected
67
85
  3. Confirm address checksum
68
86
 
69
87
  ### ABI Decoding Failed
88
+
70
89
  ```
71
90
  Error decoding string: Unknown
72
91
  ```
92
+
73
93
  **Cause:** Non-standard ERC20 implementation.
74
94
  **Solution:**
95
+
75
96
  1. Use `--verbose` to see raw data
76
97
  2. Token may use bytes32 for name/symbol
77
98
  3. Some tokens have non-standard decimals
78
99
 
79
100
  ### Verification Check Failed
101
+
80
102
  ```
81
103
  Verification check error: API key invalid
82
104
  ```
105
+
83
106
  **Cause:** Etherscan API key issues.
84
107
  **Solution:**
108
+
85
109
  1. Set `ETHERSCAN_API_KEY` environment variable
86
110
  2. Use `--etherscan-key` flag
87
111
  3. Check API key is valid for that chain
@@ -89,21 +113,27 @@ Verification check error: API key invalid
89
113
  ## Token Analysis Errors
90
114
 
91
115
  ### Risk Analysis Incomplete
116
+
92
117
  ```
93
118
  Warning: Some risk indicators could not be checked
94
119
  ```
120
+
95
121
  **Cause:** Limited bytecode or API access.
96
122
  **Solution:**
123
+
97
124
  1. Check if contract is verified
98
125
  2. Provide Etherscan API key
99
126
  3. Some indicators require source code
100
127
 
101
128
  ### Proxy Detection Failed
129
+
102
130
  ```
103
131
  Warning: Could not determine if contract is proxy
104
132
  ```
133
+
105
134
  **Cause:** Storage slot access issue.
106
135
  **Solution:**
136
+
107
137
  1. Some RPCs don't support eth_getStorageAt
108
138
  2. Use a full node RPC
109
139
  3. Proxy detection is best-effort
@@ -111,21 +141,27 @@ Warning: Could not determine if contract is proxy
111
141
  ## Environment Errors
112
142
 
113
143
  ### Missing Dependencies
144
+
114
145
  ```
115
146
  ImportError: requests library required
116
147
  ```
148
+
117
149
  **Cause:** Python requests not installed.
118
150
  **Solution:**
151
+
119
152
  ```bash
120
153
  pip install requests
121
154
  ```
122
155
 
123
156
  ### Environment Variable Missing
157
+
124
158
  ```
125
159
  Error: No RPC URL configured
126
160
  ```
161
+
127
162
  **Cause:** Chain RPC URL not found.
128
163
  **Solution:**
164
+
129
165
  1. Set `{CHAIN}_RPC_URL` environment variable
130
166
  2. Use `--rpc-url` flag
131
167
  3. Check config/settings.yaml
@@ -153,11 +189,13 @@ The system uses this fallback chain for RPC failures:
153
189
  ## Debug Mode
154
190
 
155
191
  Enable verbose output for troubleshooting:
192
+
156
193
  ```bash
157
194
  python launch_tracker.py --verbose recent --chain ethereum
158
195
  ```
159
196
 
160
197
  This shows:
198
+
161
199
  - RPC requests being made
162
200
  - Raw response data
163
201
  - Parsing steps
@@ -3,6 +3,7 @@
3
3
  ## Recent Token Launches
4
4
 
5
5
  ### Basic Usage
6
+
6
7
  ```bash
7
8
  # Show launches from last 24 hours on Ethereum
8
9
  python launch_tracker.py recent --chain ethereum
@@ -20,6 +21,7 @@ python launch_tracker.py recent --chain ethereum
20
21
  ```
21
22
 
22
23
  ### With Risk Analysis
24
+
23
25
  ```bash
24
26
  # Include token and contract analysis
25
27
  python launch_tracker.py recent --chain base --analyze --hours 12
@@ -28,12 +30,14 @@ python launch_tracker.py recent --chain base --analyze --hours 12
28
30
  ```
29
31
 
30
32
  ### Filter by DEX
33
+
31
34
  ```bash
32
35
  # Only show Uniswap V2 launches
33
36
  python launch_tracker.py recent --chain ethereum --dex "Uniswap V2"
34
37
  ```
35
38
 
36
39
  ### JSON Output
40
+
37
41
  ```bash
38
42
  # Get JSON for programmatic use
39
43
  python launch_tracker.py -f json recent --chain bsc --hours 6 --limit 10
@@ -42,6 +46,7 @@ python launch_tracker.py -f json recent --chain bsc --hours 6 --limit 10
42
46
  ## Token Details
43
47
 
44
48
  ### Get Full Token Information
49
+
45
50
  ```bash
46
51
  python launch_tracker.py detail \
47
52
  --address 0x6982508145454ce325ddbe47a25d4ec3d2311933 \
@@ -90,6 +95,7 @@ python launch_tracker.py detail \
90
95
  ## Risk Analysis
91
96
 
92
97
  ### Analyze Token Contract
98
+
93
99
  ```bash
94
100
  python launch_tracker.py risk \
95
101
  --address 0x1234567890abcdef1234567890abcdef12345678 \
@@ -125,6 +131,7 @@ python launch_tracker.py risk \
125
131
  ```
126
132
 
127
133
  ### With Etherscan Verification
134
+
128
135
  ```bash
129
136
  # Include contract verification check
130
137
  python launch_tracker.py risk \
@@ -136,6 +143,7 @@ python launch_tracker.py risk \
136
143
  ## Launch Summary
137
144
 
138
145
  ### Cross-Chain Summary
146
+
139
147
  ```bash
140
148
  python launch_tracker.py summary --hours 24
141
149
 
@@ -162,6 +170,7 @@ python launch_tracker.py summary --hours 24
162
170
  ```
163
171
 
164
172
  ### Specific Chains Only
173
+
165
174
  ```bash
166
175
  # Only Ethereum and Base
167
176
  python launch_tracker.py summary --chains ethereum,base --hours 12
@@ -170,6 +179,7 @@ python launch_tracker.py summary --chains ethereum,base --hours 12
170
179
  ## List DEXes and Chains
171
180
 
172
181
  ### Show Supported Chains
182
+
173
183
  ```bash
174
184
  python launch_tracker.py chains
175
185
 
@@ -187,6 +197,7 @@ python launch_tracker.py chains
187
197
  ```
188
198
 
189
199
  ### Show DEXes for Chain
200
+
190
201
  ```bash
191
202
  python launch_tracker.py dexes --chain bsc
192
203
 
@@ -201,6 +212,7 @@ python launch_tracker.py dexes --chain bsc
201
212
  ```
202
213
 
203
214
  ### All DEXes (JSON)
215
+
204
216
  ```bash
205
217
  python launch_tracker.py -f json dexes
206
218
  ```
@@ -208,6 +220,7 @@ python launch_tracker.py -f json dexes
208
220
  ## Custom RPC Usage
209
221
 
210
222
  ### Use Custom RPC Endpoint
223
+
211
224
  ```bash
212
225
  python launch_tracker.py recent \
213
226
  --chain ethereum \
@@ -215,6 +228,7 @@ python launch_tracker.py recent \
215
228
  ```
216
229
 
217
230
  ### Via Environment Variable
231
+
218
232
  ```bash
219
233
  export ETHEREUM_RPC_URL=https://mainnet.infura.io/v3/YOUR_PROJECT_ID
220
234
  python launch_tracker.py recent --chain ethereum
@@ -223,6 +237,7 @@ python launch_tracker.py recent --chain ethereum
223
237
  ## Verbose Output
224
238
 
225
239
  ### Debug Mode
240
+
226
241
  ```bash
227
242
  python launch_tracker.py --verbose recent --chain base --hours 1
228
243
 
@@ -238,6 +253,7 @@ python launch_tracker.py --verbose recent --chain base --hours 1
238
253
  ## Common Workflows
239
254
 
240
255
  ### Find High-Risk New Tokens
256
+
241
257
  ```bash
242
258
  # Get recent launches with analysis, output as JSON
243
259
  python launch_tracker.py -f json recent \
@@ -251,6 +267,7 @@ jq '.[] | select(.analysis.risk_score >= 70)' launches.json
251
267
  ```
252
268
 
253
269
  ### Monitor Multiple Chains
270
+
254
271
  ```bash
255
272
  #!/bin/bash
256
273
  for chain in ethereum bsc base arbitrum; do
@@ -260,6 +277,7 @@ done
260
277
  ```
261
278
 
262
279
  ### Export to CSV (via jq)
280
+
263
281
  ```bash
264
282
  python launch_tracker.py -f json recent --chain ethereum --hours 24 | \
265
283
  jq -r '.[] | [.pair.timestamp, .pair.dex, .token_info.symbol // "???", .analysis.risk_score // 0] | @csv'
@@ -268,6 +286,7 @@ python launch_tracker.py -f json recent --chain ethereum --hours 24 | \
268
286
  ## Integration Examples
269
287
 
270
288
  ### Python Import
289
+
271
290
  ```python
272
291
  from event_monitor import EventMonitor
273
292
  from token_analyzer import TokenAnalyzer
@@ -1,7 +1,9 @@
1
- # Implementation Guide
1
+ ## Implementation Guide
2
2
 
3
3
  ### Step 1: Configure Data Sources
4
+
4
5
  Set up connections to crypto data providers:
6
+
5
7
  1. Use Read tool to load API credentials from ${CLAUDE_SKILL_DIR}/config/crypto-apis.env
6
8
  2. Configure blockchain RPC endpoints for target networks
7
9
  3. Set up exchange API connections if required
@@ -9,7 +11,9 @@ Set up connections to crypto data providers:
9
11
  5. Test connectivity and authentication
10
12
 
11
13
  ### Step 2: Query Crypto Data
14
+
12
15
  Retrieve relevant blockchain and market data:
16
+
13
17
  1. Use Bash(crypto:launch-*) to execute crypto data queries
14
18
  2. Fetch real-time prices, volumes, and market cap data
15
19
  3. Query blockchain for on-chain metrics and transactions
@@ -17,7 +21,9 @@ Retrieve relevant blockchain and market data:
17
21
  5. Aggregate data from multiple sources for accuracy
18
22
 
19
23
  ### Step 3: Analyze and Process
24
+
20
25
  Process crypto data to generate insights:
26
+
21
27
  - Calculate key metrics (returns, volatility, correlation)
22
28
  - Identify patterns and anomalies in data
23
29
  - Apply technical indicators or on-chain signals
@@ -25,7 +31,9 @@ Process crypto data to generate insights:
25
31
  - Generate actionable insights and alerts
26
32
 
27
33
  ### Step 4: Generate Reports
34
+
28
35
  Document findings in ${CLAUDE_SKILL_DIR}/crypto-reports/:
36
+
29
37
  - Market summary with key price movements
30
38
  - Detailed analysis with charts and metrics
31
39
  - Trading signals or opportunity recommendations
@@ -19,6 +19,7 @@ PAIR_CREATED_TOPIC = "0x0d3648bd0f6ba80134a33ba9275ac585d9d315f0ad8355cddefde31a
19
19
  @dataclass
20
20
  class DexFactory:
21
21
  """DEX factory configuration."""
22
+
22
23
  name: str
23
24
  address: str
24
25
  version: str # v2 or v3
@@ -28,6 +29,7 @@ class DexFactory:
28
29
  @dataclass
29
30
  class ChainConfig:
30
31
  """Chain configuration."""
32
+
31
33
  name: str
32
34
  chain_id: int
33
35
  rpc_url: str
@@ -31,6 +31,7 @@ from dex_sources import (
31
31
  @dataclass
32
32
  class PairCreated:
33
33
  """New trading pair event."""
34
+
34
35
  block_number: int
35
36
  tx_hash: str
36
37
  timestamp: int
@@ -45,6 +46,7 @@ class PairCreated:
45
46
  @dataclass
46
47
  class TokenBasicInfo:
47
48
  """Basic token info from RPC."""
49
+
48
50
  address: str
49
51
  name: str
50
52
  symbol: str
@@ -54,12 +56,7 @@ class TokenBasicInfo:
54
56
  class EventMonitor:
55
57
  """Monitor blockchain events for new pairs."""
56
58
 
57
- def __init__(
58
- self,
59
- chain: str = "ethereum",
60
- rpc_url: str = None,
61
- verbose: bool = False
62
- ):
59
+ def __init__(self, chain: str = "ethereum", rpc_url: str = None, verbose: bool = False):
63
60
  """Initialize event monitor.
64
61
 
65
62
  Args:
@@ -69,10 +66,7 @@ class EventMonitor:
69
66
  """
70
67
  self.chain = chain.lower()
71
68
  self.config = get_chain_config(chain)
72
- self.rpc_url = rpc_url or os.environ.get(
73
- f"{chain.upper()}_RPC_URL",
74
- self.config.rpc_url
75
- )
69
+ self.rpc_url = rpc_url or os.environ.get(f"{chain.upper()}_RPC_URL", self.config.rpc_url)
76
70
  self.verbose = verbose
77
71
  # Use a size-limited cache to prevent memory leaks on long-running instances
78
72
  # Keeps most recent 1000 block timestamps
@@ -111,10 +105,7 @@ class EventMonitor:
111
105
  if block_number in self._block_cache:
112
106
  return self._block_cache[block_number]
113
107
 
114
- block = self._rpc_call(
115
- "eth_getBlockByNumber",
116
- [hex(block_number), False]
117
- )
108
+ block = self._rpc_call("eth_getBlockByNumber", [hex(block_number), False])
118
109
 
119
110
  if block:
120
111
  timestamp = int(block.get("timestamp", "0x0"), 16)
@@ -136,11 +127,7 @@ class EventMonitor:
136
127
  result = self._rpc_call("eth_blockNumber")
137
128
  return int(result, 16)
138
129
 
139
- def get_recent_pairs(
140
- self,
141
- hours: int = 24,
142
- dex: str = None
143
- ) -> List[PairCreated]:
130
+ def get_recent_pairs(self, hours: int = 24, dex: str = None) -> List[PairCreated]:
144
131
  """Get recently created pairs.
145
132
 
146
133
  Args:
@@ -168,12 +155,17 @@ class EventMonitor:
168
155
 
169
156
  for factory_addr in factory_addresses:
170
157
  try:
171
- logs = self._rpc_call("eth_getLogs", [{
172
- "fromBlock": hex(from_block),
173
- "toBlock": "latest",
174
- "address": factory_addr,
175
- "topics": [PAIR_CREATED_TOPIC],
176
- }])
158
+ logs = self._rpc_call(
159
+ "eth_getLogs",
160
+ [
161
+ {
162
+ "fromBlock": hex(from_block),
163
+ "toBlock": "latest",
164
+ "address": factory_addr,
165
+ "topics": [PAIR_CREATED_TOPIC],
166
+ }
167
+ ],
168
+ )
177
169
 
178
170
  for log in logs or []:
179
171
  pair = self._parse_pair_created(log, factory_addr)
@@ -189,11 +181,7 @@ class EventMonitor:
189
181
 
190
182
  return pairs
191
183
 
192
- def _parse_pair_created(
193
- self,
194
- log: Dict,
195
- factory_address: str
196
- ) -> Optional[PairCreated]:
184
+ def _parse_pair_created(self, log: Dict, factory_address: str) -> Optional[PairCreated]:
197
185
  """Parse PairCreated event log."""
198
186
  try:
199
187
  block_number = int(log["blockNumber"], 16)
@@ -265,10 +253,7 @@ class EventMonitor:
265
253
  def _call_contract(self, address: str, data: str) -> Optional[str]:
266
254
  """Make eth_call to contract."""
267
255
  try:
268
- result = self._rpc_call("eth_call", [
269
- {"to": address, "data": data},
270
- "latest"
271
- ])
256
+ result = self._rpc_call("eth_call", [{"to": address, "data": data}, "latest"])
272
257
  return result if result and result != "0x" else None
273
258
  except Exception:
274
259
  return None
@@ -289,7 +274,7 @@ class EventMonitor:
289
274
  # ABI encoded string: offset (32 bytes) + length (32 bytes) + data
290
275
  if len(data) >= 128:
291
276
  length = int(data[64:128], 16)
292
- string_data = data[128:128 + length * 2]
277
+ string_data = data[128 : 128 + length * 2]
293
278
  return bytes.fromhex(string_data).decode("utf-8", errors="ignore")
294
279
 
295
280
  return bytes.fromhex(data).decode("utf-8", errors="ignore").strip("\x00")
@@ -58,7 +58,7 @@ def format_risk_badge(score: int) -> str:
58
58
 
59
59
  def format_supply(supply: int, decimals: int) -> str:
60
60
  """Format token supply."""
61
- value = supply / (10 ** decimals)
61
+ value = supply / (10**decimals)
62
62
 
63
63
  if value >= 1e12:
64
64
  return f"{value / 1e12:.2f}T"
@@ -72,11 +72,7 @@ def format_supply(supply: int, decimals: int) -> str:
72
72
  return f"{value:.2f}"
73
73
 
74
74
 
75
- def format_new_pairs_table(
76
- pairs: List[Any],
77
- token_infos: Dict[str, Any],
78
- analyses: Dict[str, Any]
79
- ) -> str:
75
+ def format_new_pairs_table(pairs: List[Any], token_infos: Dict[str, Any], analyses: Dict[str, Any]) -> str:
80
76
  """Format new pairs as table.
81
77
 
82
78
  Args:
@@ -110,10 +106,7 @@ def format_new_pairs_table(
110
106
  pair_str = format_address(pair.pair_address, 8)
111
107
  time_str = format_age(pair.timestamp)
112
108
 
113
- lines.append(
114
- f"{time_str:<12} {token_str:<20} {pair.dex:<15} "
115
- f"{pair.chain:<10} {risk_str:<15} {pair_str:<18}"
116
- )
109
+ lines.append(f"{time_str:<12} {token_str:<20} {pair.dex:<15} {pair.chain:<10} {risk_str:<15} {pair_str:<18}")
117
110
 
118
111
  lines.append("=" * 90)
119
112
  lines.append(f"Total: {len(pairs)} new pairs")
@@ -121,12 +114,7 @@ def format_new_pairs_table(
121
114
  return "\n".join(lines)
122
115
 
123
116
 
124
- def format_launch_detail(
125
- pair: Any,
126
- token_info: Any,
127
- analysis: Any,
128
- chain_config: Any
129
- ) -> str:
117
+ def format_launch_detail(pair: Any, token_info: Any, analysis: Any, chain_config: Any) -> str:
130
118
  """Format detailed launch info.
131
119
 
132
120
  Args:
@@ -158,26 +146,30 @@ def format_launch_detail(
158
146
  ]
159
147
 
160
148
  if token_info:
161
- lines.extend([
162
- "TOKEN INFO",
163
- "-" * 60,
164
- f"Decimals: {token_info.decimals}",
165
- f"Total Supply: {format_supply(token_info.total_supply, token_info.decimals)}",
166
- f"Owner: {format_address(token_info.owner) if token_info.owner else 'None'}",
167
- f"Verified: {'Yes' if token_info.is_verified else 'No'}",
168
- "",
169
- ])
149
+ lines.extend(
150
+ [
151
+ "TOKEN INFO",
152
+ "-" * 60,
153
+ f"Decimals: {token_info.decimals}",
154
+ f"Total Supply: {format_supply(token_info.total_supply, token_info.decimals)}",
155
+ f"Owner: {format_address(token_info.owner) if token_info.owner else 'None'}",
156
+ f"Verified: {'Yes' if token_info.is_verified else 'No'}",
157
+ "",
158
+ ]
159
+ )
170
160
 
171
161
  if analysis:
172
- lines.extend([
173
- "RISK ANALYSIS",
174
- "-" * 60,
175
- f"Risk Score: {analysis.risk_score}/100 {format_risk_badge(analysis.risk_score)}",
176
- f"Is Proxy: {'Yes' if analysis.is_proxy else 'No'}",
177
- f"Ownership: {'Renounced' if analysis.ownership_renounced else 'Active'}",
178
- "",
179
- "Indicators:",
180
- ])
162
+ lines.extend(
163
+ [
164
+ "RISK ANALYSIS",
165
+ "-" * 60,
166
+ f"Risk Score: {analysis.risk_score}/100 {format_risk_badge(analysis.risk_score)}",
167
+ f"Is Proxy: {'Yes' if analysis.is_proxy else 'No'}",
168
+ f"Ownership: {'Renounced' if analysis.ownership_renounced else 'Active'}",
169
+ "",
170
+ "Indicators:",
171
+ ]
172
+ )
181
173
 
182
174
  for ind in analysis.indicators:
183
175
  severity_marker = {
@@ -254,11 +246,7 @@ def format_json(data: Any) -> str:
254
246
  if hasattr(data, "__dict__"):
255
247
  return json.dumps(vars(data), indent=2, default=str)
256
248
  elif isinstance(data, list):
257
- return json.dumps(
258
- [vars(x) if hasattr(x, "__dict__") else x for x in data],
259
- indent=2,
260
- default=str
261
- )
249
+ return json.dumps([vars(x) if hasattr(x, "__dict__") else x for x in data], indent=2, default=str)
262
250
  else:
263
251
  return json.dumps(data, indent=2, default=str)
264
252