@intentsolutionsio/mempool-analyzer 1.0.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 (28) hide show
  1. package/.claude-plugin/plugin.json +22 -0
  2. package/LICENSE +21 -0
  3. package/README.md +97 -0
  4. package/agents/mempool-agent.md +158 -0
  5. package/package.json +43 -0
  6. package/skills/analyzing-mempool/ARD.md +146 -0
  7. package/skills/analyzing-mempool/PRD.md +71 -0
  8. package/skills/analyzing-mempool/SKILL.md +110 -0
  9. package/skills/analyzing-mempool/config/settings.yaml +43 -0
  10. package/skills/analyzing-mempool/references/errors.md +122 -0
  11. package/skills/analyzing-mempool/references/examples.md +189 -0
  12. package/skills/analyzing-mempool/references/implementation.md +67 -0
  13. package/skills/analyzing-mempool/scripts/formatters.py +244 -0
  14. package/skills/analyzing-mempool/scripts/gas_analyzer.py +299 -0
  15. package/skills/analyzing-mempool/scripts/mempool_analyzer.py +320 -0
  16. package/skills/analyzing-mempool/scripts/mev_detector.py +387 -0
  17. package/skills/analyzing-mempool/scripts/rpc_client.py +311 -0
  18. package/skills/analyzing-mempool/scripts/tx_decoder.py +273 -0
  19. package/skills/skill-adapter/assets/README.md +6 -0
  20. package/skills/skill-adapter/assets/config-template.json +32 -0
  21. package/skills/skill-adapter/assets/skill-schema.json +28 -0
  22. package/skills/skill-adapter/assets/test-data.json +27 -0
  23. package/skills/skill-adapter/references/README.md +4 -0
  24. package/skills/skill-adapter/references/best-practices.md +69 -0
  25. package/skills/skill-adapter/references/examples.md +73 -0
  26. package/skills/skill-adapter/scripts/README.md +8 -0
  27. package/skills/skill-adapter/scripts/helper-template.sh +42 -0
  28. package/skills/skill-adapter/scripts/validation.sh +32 -0
@@ -0,0 +1,273 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ Transaction Decoder
4
+
5
+ Decode Ethereum transaction input data using known ABIs.
6
+
7
+ Author: Jeremy Longshore <jeremy@intentsolutions.io>
8
+ Version: 1.0.0
9
+ License: MIT
10
+ """
11
+
12
+ from typing import Any, Dict, Optional
13
+ from dataclasses import dataclass
14
+
15
+
16
+ # Common DEX method signatures (first 4 bytes of keccak256)
17
+ METHOD_SIGNATURES = {
18
+ # Uniswap V2 Router
19
+ "0x38ed1739": {"name": "swapExactTokensForTokens", "type": "swap"},
20
+ "0x8803dbee": {"name": "swapTokensForExactTokens", "type": "swap"},
21
+ "0x7ff36ab5": {"name": "swapExactETHForTokens", "type": "swap"},
22
+ "0x4a25d94a": {"name": "swapTokensForExactETH", "type": "swap"},
23
+ "0x18cbafe5": {"name": "swapExactTokensForETH", "type": "swap"},
24
+ "0xfb3bdb41": {"name": "swapETHForExactTokens", "type": "swap"},
25
+ "0xe8e33700": {"name": "addLiquidity", "type": "liquidity"},
26
+ "0xf305d719": {"name": "addLiquidityETH", "type": "liquidity"},
27
+ "0xbaa2abde": {"name": "removeLiquidity", "type": "liquidity"},
28
+ "0x02751cec": {"name": "removeLiquidityETH", "type": "liquidity"},
29
+
30
+ # Uniswap V3 Router
31
+ "0x414bf389": {"name": "exactInputSingle", "type": "swap"},
32
+ "0xc04b8d59": {"name": "exactInput", "type": "swap"},
33
+ "0xdb3e2198": {"name": "exactOutputSingle", "type": "swap"},
34
+ "0xf28c0498": {"name": "exactOutput", "type": "swap"},
35
+ "0x5ae401dc": {"name": "multicall", "type": "multicall"},
36
+ "0xac9650d8": {"name": "multicall", "type": "multicall"},
37
+
38
+ # ERC20
39
+ "0xa9059cbb": {"name": "transfer", "type": "transfer"},
40
+ "0x23b872dd": {"name": "transferFrom", "type": "transfer"},
41
+ "0x095ea7b3": {"name": "approve", "type": "approval"},
42
+
43
+ # Common
44
+ "0x": {"name": "ETH Transfer", "type": "transfer"},
45
+ }
46
+
47
+ # Known contract addresses
48
+ KNOWN_CONTRACTS = {
49
+ # Ethereum Mainnet
50
+ "0x7a250d5630b4cf539739df2c5dacb4c659f2488d": "Uniswap V2 Router",
51
+ "0xe592427a0aece92de3edee1f18e0157c05861564": "Uniswap V3 Router",
52
+ "0x68b3465833fb72a70ecdf485e0e4c7bd8665fc45": "Uniswap Universal Router",
53
+ "0xd9e1ce17f2641f24ae83637ab66a2cca9c378b9f": "SushiSwap Router",
54
+ "0x1111111254fb6c44bac0bed2854e76f90643097d": "1inch Router",
55
+ "0xdef1c0ded9bec7f1a1670819833240f027b25eff": "0x Exchange Proxy",
56
+ "0x881d40237659c251811cec9c364ef91dc08d300c": "Metamask Swap Router",
57
+
58
+ # Tokens
59
+ "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2": "WETH",
60
+ "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48": "USDC",
61
+ "0xdac17f958d2ee523a2206206994597c13d831ec7": "USDT",
62
+ "0x6b175474e89094c44da98b954eedeac495271d0f": "DAI",
63
+ }
64
+
65
+
66
+ @dataclass
67
+ class DecodedCall:
68
+ """Decoded function call."""
69
+ method_name: str
70
+ method_type: str # swap, transfer, approval, liquidity, multicall, unknown
71
+ contract_name: Optional[str]
72
+ raw_signature: str
73
+ params: Dict[str, Any]
74
+
75
+
76
+ @dataclass
77
+ class SwapInfo:
78
+ """Detected swap information."""
79
+ dex: str
80
+ method: str
81
+ token_in: Optional[str]
82
+ token_out: Optional[str]
83
+ amount_in: Optional[int]
84
+ amount_out_min: Optional[int]
85
+ is_exact_input: bool
86
+
87
+
88
+ class TransactionDecoder:
89
+ """Decode Ethereum transaction input data."""
90
+
91
+ def __init__(self, verbose: bool = False):
92
+ """Initialize decoder."""
93
+ self.verbose = verbose
94
+
95
+ def decode_input(self, input_data: str, to_address: str = None) -> DecodedCall:
96
+ """Decode transaction input data.
97
+
98
+ Args:
99
+ input_data: Transaction input (hex string)
100
+ to_address: Destination contract address
101
+
102
+ Returns:
103
+ DecodedCall with decoded information
104
+ """
105
+ if not input_data or input_data == "0x":
106
+ return DecodedCall(
107
+ method_name="ETH Transfer",
108
+ method_type="transfer",
109
+ contract_name=self._get_contract_name(to_address) if to_address else None,
110
+ raw_signature="0x",
111
+ params={},
112
+ )
113
+
114
+ # Get method signature (first 4 bytes)
115
+ signature = input_data[:10].lower()
116
+
117
+ method_info = METHOD_SIGNATURES.get(signature, {
118
+ "name": "Unknown",
119
+ "type": "unknown",
120
+ })
121
+
122
+ contract_name = self._get_contract_name(to_address) if to_address else None
123
+
124
+ return DecodedCall(
125
+ method_name=method_info["name"],
126
+ method_type=method_info["type"],
127
+ contract_name=contract_name,
128
+ raw_signature=signature,
129
+ params=self._decode_params(input_data, signature),
130
+ )
131
+
132
+ def _get_contract_name(self, address: str) -> Optional[str]:
133
+ """Get known contract name."""
134
+ if not address:
135
+ return None
136
+ return KNOWN_CONTRACTS.get(address.lower())
137
+
138
+ def _decode_params(self, input_data: str, signature: str) -> Dict[str, Any]:
139
+ """Decode function parameters (simplified)."""
140
+ if len(input_data) < 10:
141
+ return {}
142
+
143
+ # Remove signature
144
+ data = input_data[10:]
145
+ if not data:
146
+ return {}
147
+
148
+ params = {}
149
+
150
+ # Parse 32-byte chunks
151
+ chunks = [data[i:i+64] for i in range(0, len(data), 64)]
152
+
153
+ # For swaps, try to extract amounts
154
+ if signature in ["0x38ed1739", "0x8803dbee"]:
155
+ # swapExactTokensForTokens / swapTokensForExactTokens
156
+ if len(chunks) >= 2:
157
+ params["amountIn"] = int(chunks[0], 16) if chunks[0] else 0
158
+ params["amountOutMin"] = int(chunks[1], 16) if chunks[1] else 0
159
+
160
+ elif signature in ["0x7ff36ab5", "0xfb3bdb41"]:
161
+ # swapExactETHForTokens / swapETHForExactTokens
162
+ if len(chunks) >= 1:
163
+ params["amountOutMin"] = int(chunks[0], 16) if chunks[0] else 0
164
+
165
+ elif signature == "0xa9059cbb":
166
+ # transfer(address, uint256)
167
+ if len(chunks) >= 2:
168
+ params["to"] = "0x" + chunks[0][-40:]
169
+ params["amount"] = int(chunks[1], 16) if chunks[1] else 0
170
+
171
+ elif signature == "0x095ea7b3":
172
+ # approve(address, uint256)
173
+ if len(chunks) >= 2:
174
+ params["spender"] = "0x" + chunks[0][-40:]
175
+ params["amount"] = int(chunks[1], 16) if chunks[1] else 0
176
+
177
+ return params
178
+
179
+ def identify_dex_swap(self, input_data: str, to_address: str) -> Optional[SwapInfo]:
180
+ """Identify if transaction is a DEX swap.
181
+
182
+ Args:
183
+ input_data: Transaction input data
184
+ to_address: Destination address
185
+
186
+ Returns:
187
+ SwapInfo if swap detected, None otherwise
188
+ """
189
+ decoded = self.decode_input(input_data, to_address)
190
+
191
+ if decoded.method_type != "swap":
192
+ return None
193
+
194
+ dex = decoded.contract_name or "Unknown DEX"
195
+ is_exact_input = "exact" in decoded.method_name.lower() and "input" in decoded.method_name.lower()
196
+
197
+ return SwapInfo(
198
+ dex=dex,
199
+ method=decoded.method_name,
200
+ token_in=None, # Would need path decoding
201
+ token_out=None,
202
+ amount_in=decoded.params.get("amountIn"),
203
+ amount_out_min=decoded.params.get("amountOutMin"),
204
+ is_exact_input=is_exact_input,
205
+ )
206
+
207
+ def classify_transaction(self, tx: Dict) -> str:
208
+ """Classify transaction type.
209
+
210
+ Args:
211
+ tx: Transaction dict with 'input' and 'to' fields
212
+
213
+ Returns:
214
+ Transaction type string
215
+ """
216
+ input_data = tx.get("input_data", "") or tx.get("input", "")
217
+ to_address = tx.get("to_address", "") or tx.get("to", "")
218
+
219
+ decoded = self.decode_input(input_data, to_address)
220
+ return decoded.method_type
221
+
222
+ def estimate_attached_eth_usd_value(
223
+ self,
224
+ tx: Dict,
225
+ eth_price: float = 3000.0
226
+ ) -> float:
227
+ """Estimate USD value of ETH attached to transaction (msg.value).
228
+
229
+ Note: This only calculates the USD value of ETH sent with the transaction.
230
+ For token swaps, the actual value is in the tokens being exchanged,
231
+ not the attached ETH (which is often zero). Use this for ETH transfers
232
+ or transactions that include ETH payment.
233
+
234
+ Args:
235
+ tx: Transaction dict with 'value' field (in wei)
236
+ eth_price: Current ETH price in USD
237
+
238
+ Returns:
239
+ USD value of attached ETH (not the full transaction value for swaps)
240
+ """
241
+ value_wei = tx.get("value", 0)
242
+ if isinstance(value_wei, str):
243
+ value_wei = int(value_wei, 16) if value_wei.startswith("0x") else int(value_wei)
244
+
245
+ value_eth = value_wei / 10**18
246
+ return value_eth * eth_price
247
+
248
+ # Backward compatibility alias
249
+ estimate_usd_value = estimate_attached_eth_usd_value
250
+
251
+
252
+ def main():
253
+ """CLI entry point for testing."""
254
+ decoder = TransactionDecoder(verbose=True)
255
+
256
+ # Test decode
257
+ test_cases = [
258
+ ("0x38ed1739" + "0" * 256, "0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D"),
259
+ ("0xa9059cbb" + "0" * 128, "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2"),
260
+ ("0x", None),
261
+ ]
262
+
263
+ print("=== Transaction Decoding Tests ===")
264
+ for input_data, to_addr in test_cases:
265
+ decoded = decoder.decode_input(input_data, to_addr)
266
+ print(f"\nInput: {input_data[:20]}...")
267
+ print(f" Method: {decoded.method_name}")
268
+ print(f" Type: {decoded.method_type}")
269
+ print(f" Contract: {decoded.contract_name or 'Unknown'}")
270
+
271
+
272
+ if __name__ == "__main__":
273
+ main()
@@ -0,0 +1,6 @@
1
+ # Assets
2
+
3
+ Bundled resources for mempool-analyzer skill
4
+
5
+ - [ ] alert_templates/: Directory containing templates for different types of alerts (email, Slack, etc.).
6
+ - [ ] example_transactions/: Directory containing example transactions for analysis.
@@ -0,0 +1,32 @@
1
+ {
2
+ "skill": {
3
+ "name": "skill-name",
4
+ "version": "1.0.0",
5
+ "enabled": true,
6
+ "settings": {
7
+ "verbose": false,
8
+ "autoActivate": true,
9
+ "toolRestrictions": true
10
+ }
11
+ },
12
+ "triggers": {
13
+ "keywords": [
14
+ "example-trigger-1",
15
+ "example-trigger-2"
16
+ ],
17
+ "patterns": []
18
+ },
19
+ "tools": {
20
+ "allowed": [
21
+ "Read",
22
+ "Grep",
23
+ "Bash"
24
+ ],
25
+ "restricted": []
26
+ },
27
+ "metadata": {
28
+ "author": "Plugin Author",
29
+ "category": "general",
30
+ "tags": []
31
+ }
32
+ }
@@ -0,0 +1,28 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema#",
3
+ "title": "Claude Skill Configuration",
4
+ "type": "object",
5
+ "required": ["name", "description"],
6
+ "properties": {
7
+ "name": {
8
+ "type": "string",
9
+ "pattern": "^[a-z0-9-]+$",
10
+ "maxLength": 64,
11
+ "description": "Skill identifier (lowercase, hyphens only)"
12
+ },
13
+ "description": {
14
+ "type": "string",
15
+ "maxLength": 1024,
16
+ "description": "What the skill does and when to use it"
17
+ },
18
+ "allowed-tools": {
19
+ "type": "string",
20
+ "description": "Comma-separated list of allowed tools"
21
+ },
22
+ "version": {
23
+ "type": "string",
24
+ "pattern": "^\\d+\\.\\d+\\.\\d+$",
25
+ "description": "Semantic version (x.y.z)"
26
+ }
27
+ }
28
+ }
@@ -0,0 +1,27 @@
1
+ {
2
+ "testCases": [
3
+ {
4
+ "name": "Basic activation test",
5
+ "input": "trigger phrase example",
6
+ "expected": {
7
+ "activated": true,
8
+ "toolsUsed": ["Read", "Grep"],
9
+ "success": true
10
+ }
11
+ },
12
+ {
13
+ "name": "Complex workflow test",
14
+ "input": "multi-step trigger example",
15
+ "expected": {
16
+ "activated": true,
17
+ "steps": 3,
18
+ "toolsUsed": ["Read", "Write", "Bash"],
19
+ "success": true
20
+ }
21
+ }
22
+ ],
23
+ "fixtures": {
24
+ "sampleInput": "example data",
25
+ "expectedOutput": "processed result"
26
+ }
27
+ }
@@ -0,0 +1,4 @@
1
+ # References
2
+
3
+ Bundled resources for mempool-analyzer skill
4
+
@@ -0,0 +1,69 @@
1
+ # Skill Best Practices
2
+
3
+ Guidelines for optimal skill usage and development.
4
+
5
+ ## For Users
6
+
7
+ ### Activation Best Practices
8
+
9
+ 1. **Use Clear Trigger Phrases**
10
+ - Match phrases from skill description
11
+ - Be specific about intent
12
+ - Provide necessary context
13
+
14
+ 2. **Provide Sufficient Context**
15
+ - Include relevant file paths
16
+ - Specify scope of analysis
17
+ - Mention any constraints
18
+
19
+ 3. **Understand Tool Permissions**
20
+ - Check allowed-tools in frontmatter
21
+ - Know what the skill can/cannot do
22
+ - Request appropriate actions
23
+
24
+ ### Workflow Optimization
25
+
26
+ - Start with simple requests
27
+ - Build up to complex workflows
28
+ - Verify each step before proceeding
29
+ - Use skill consistently for related tasks
30
+
31
+ ## For Developers
32
+
33
+ ### Skill Development Guidelines
34
+
35
+ 1. **Clear Descriptions**
36
+ - Include explicit trigger phrases
37
+ - Document all capabilities
38
+ - Specify limitations
39
+
40
+ 2. **Proper Tool Permissions**
41
+ - Use minimal necessary tools
42
+ - Document security implications
43
+ - Test with restricted tools
44
+
45
+ 3. **Comprehensive Documentation**
46
+ - Provide usage examples
47
+ - Document common pitfalls
48
+ - Include troubleshooting guide
49
+
50
+ ### Maintenance
51
+
52
+ - Keep version updated
53
+ - Test after tool updates
54
+ - Monitor user feedback
55
+ - Iterate on descriptions
56
+
57
+ ## Performance Tips
58
+
59
+ - Scope skills to specific domains
60
+ - Avoid overlapping trigger phrases
61
+ - Keep descriptions under 1024 chars
62
+ - Test activation reliability
63
+
64
+ ## Security Considerations
65
+
66
+ - Never include secrets in skill files
67
+ - Validate all inputs
68
+ - Use read-only tools when possible
69
+ - Document security requirements
@@ -0,0 +1,73 @@
1
+ # Skill Usage Examples
2
+
3
+ This document provides practical examples of how to use this skill effectively.
4
+
5
+ ## Basic Usage
6
+
7
+ ### Example 1: Simple Activation
8
+
9
+ **User Request:**
10
+ ```
11
+ [Describe trigger phrase here]
12
+ ```
13
+
14
+ **Skill Response:**
15
+ 1. Analyzes the request
16
+ 2. Performs the required action
17
+ 3. Returns results
18
+
19
+ ### Example 2: Complex Workflow
20
+
21
+ **User Request:**
22
+ ```
23
+ [Describe complex scenario]
24
+ ```
25
+
26
+ **Workflow:**
27
+ 1. Step 1: Initial analysis
28
+ 2. Step 2: Data processing
29
+ 3. Step 3: Result generation
30
+ 4. Step 4: Validation
31
+
32
+ ## Advanced Patterns
33
+
34
+ ### Pattern 1: Chaining Operations
35
+
36
+ Combine this skill with other tools:
37
+ ```
38
+ Step 1: Use this skill for [purpose]
39
+ Step 2: Chain with [other tool]
40
+ Step 3: Finalize with [action]
41
+ ```
42
+
43
+ ### Pattern 2: Error Handling
44
+
45
+ If issues occur:
46
+ - Check trigger phrase matches
47
+ - Verify context is available
48
+ - Review allowed-tools permissions
49
+
50
+ ## Tips & Best Practices
51
+
52
+ - ✅ Be specific with trigger phrases
53
+ - ✅ Provide necessary context
54
+ - ✅ Check tool permissions match needs
55
+ - ❌ Avoid vague requests
56
+ - ❌ Don't mix unrelated tasks
57
+
58
+ ## Common Issues
59
+
60
+ **Issue:** Skill doesn't activate
61
+ **Solution:** Use exact trigger phrases from description
62
+
63
+ **Issue:** Unexpected results
64
+ **Solution:** Check input format and context
65
+
66
+ ## See Also
67
+
68
+ - Main SKILL.md for full documentation
69
+ - scripts/ for automation helpers
70
+ - assets/ for configuration examples
71
+
72
+ ---
73
+ *[Tons of Skills](https://tonsofskills.com) by [Intent Solutions](https://intentsolutions.io) | [jeremylongshore.com](https://jeremylongshore.com)*
@@ -0,0 +1,8 @@
1
+ # Scripts
2
+
3
+ Bundled resources for mempool-analyzer skill
4
+
5
+ - [ ] gas_price_optimizer.py: Script to calculate optimal gas prices based on mempool data and EIP-1559.
6
+ - [ ] mev_detector.py: Script to identify and analyze MEV opportunities (sandwich attacks, arbitrage, liquidations).
7
+ - [ ] transaction_decoder.py: Script to decode transaction calldata and simulate transaction execution.
8
+ - [ ] alert_manager.py: Script to manage and send alerts based on configured thresholds (large transfers, high gas prices, MEV opportunities).
@@ -0,0 +1,42 @@
1
+ #!/bin/bash
2
+ # Helper script template for skill automation
3
+ # Customize this for your skill's specific needs
4
+
5
+ set -e
6
+
7
+ function show_usage() {
8
+ echo "Usage: $0 [options]"
9
+ echo ""
10
+ echo "Options:"
11
+ echo " -h, --help Show this help message"
12
+ echo " -v, --verbose Enable verbose output"
13
+ echo ""
14
+ }
15
+
16
+ # Parse arguments
17
+ VERBOSE=false
18
+
19
+ while [[ $# -gt 0 ]]; do
20
+ case $1 in
21
+ -h|--help)
22
+ show_usage
23
+ exit 0
24
+ ;;
25
+ -v|--verbose)
26
+ VERBOSE=true
27
+ shift
28
+ ;;
29
+ *)
30
+ echo "Unknown option: $1"
31
+ show_usage
32
+ exit 1
33
+ ;;
34
+ esac
35
+ done
36
+
37
+ # Your skill logic here
38
+ if [ "$VERBOSE" = true ]; then
39
+ echo "Running skill automation..."
40
+ fi
41
+
42
+ echo "✅ Complete"
@@ -0,0 +1,32 @@
1
+ #!/bin/bash
2
+ # Skill validation helper
3
+ # Validates skill activation and functionality
4
+
5
+ set -e
6
+
7
+ echo "🔍 Validating skill..."
8
+
9
+ # Check if SKILL.md exists
10
+ if [ ! -f "../SKILL.md" ]; then
11
+ echo "❌ Error: SKILL.md not found"
12
+ exit 1
13
+ fi
14
+
15
+ # Validate frontmatter
16
+ if ! grep -q "^---$" "../SKILL.md"; then
17
+ echo "❌ Error: No frontmatter found"
18
+ exit 1
19
+ fi
20
+
21
+ # Check required fields
22
+ if ! grep -q "^name:" "../SKILL.md"; then
23
+ echo "❌ Error: Missing 'name' field"
24
+ exit 1
25
+ fi
26
+
27
+ if ! grep -q "^description:" "../SKILL.md"; then
28
+ echo "❌ Error: Missing 'description' field"
29
+ exit 1
30
+ fi
31
+
32
+ echo "✅ Skill validation passed"