degenscan-intel 0.1.0__tar.gz
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.
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Marbella Collins LLC (degenscan.io)
|
|
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,124 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: degenscan-intel
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Cross-asset market-event intelligence for AI trading agents (SEC, Fed, regulators, disasters, halts, hacks, Polymarket, Hyperliquid perps). Pays per call in USDC via x402 or uses an API key.
|
|
5
|
+
Project-URL: Homepage, https://intel.degenscan.io
|
|
6
|
+
Project-URL: Documentation, https://intel.degenscan.io/llms.txt
|
|
7
|
+
Project-URL: Repository, https://github.com/tradewr333-lgtm/degenscan-intel
|
|
8
|
+
Author-email: Marbella Collins LLC <contact@degenscan.io>
|
|
9
|
+
License: MIT
|
|
10
|
+
License-File: LICENSE
|
|
11
|
+
Keywords: agentkit,ai-agents,base,federal-reserve,funding-rate,hyperliquid,langchain,market-data,market-events,mcp,polymarket,sec-edgar,trading-bot,usdc,x402
|
|
12
|
+
Classifier: Intended Audience :: Developers
|
|
13
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Topic :: Office/Business :: Financial
|
|
16
|
+
Requires-Python: >=3.10
|
|
17
|
+
Requires-Dist: httpx>=0.27
|
|
18
|
+
Provides-Extra: x402
|
|
19
|
+
Requires-Dist: eth-account>=0.13; extra == 'x402'
|
|
20
|
+
Requires-Dist: x402>=2.24; extra == 'x402'
|
|
21
|
+
Description-Content-Type: text/markdown
|
|
22
|
+
|
|
23
|
+
# degenscan-intel
|
|
24
|
+
|
|
25
|
+
Market-event intelligence for AI trading agents, paid per call in USDC (x402) or with an API key.
|
|
26
|
+
|
|
27
|
+
One normalized feed of price-moving events from ~40 primary sources — SEC EDGAR (8-K, Form 4, 13D), Federal Reserve, Federal Register, ECB/BoE/BoJ, FTC/DOJ/FDA/CFTC/FCC, USGS earthquakes, NOAA/NHC storms, Nasdaq halts, DefiLlama hacks, Polymarket odds, Hyperliquid perps — scored against an exposure graph into per-asset impacts (`direction`, `confidence`, `path`). Deterministic, sub-200 ms, every event links to its source document.
|
|
28
|
+
|
|
29
|
+
- Service: `https://intel.degenscan.io` · MCP: `POST https://intel.degenscan.io/mcp` · OpenAPI: `/openapi.json` · Docs for LLMs: `/llms.txt`
|
|
30
|
+
- Prices: $0.001–$0.02 per call (brief $0.10). No subscription needed. Free trial: 100 calls/day/IP.
|
|
31
|
+
- Operator: Marbella Collins LLC · MIT · Information and analytics only — not investment advice.
|
|
32
|
+
|
|
33
|
+
## Install
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
pip install degenscan-intel # API key / free trial
|
|
37
|
+
pip install "degenscan-intel[x402]" # + per-call USDC payments from an agent wallet
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## 20-line trading-agent loop
|
|
41
|
+
|
|
42
|
+
```python
|
|
43
|
+
import os, time
|
|
44
|
+
from degenscan_intel import Intel
|
|
45
|
+
|
|
46
|
+
# Pick ONE:
|
|
47
|
+
intel = Intel(private_key=os.environ["AGENT_WALLET_PK"]) # pays USDC on Base per call via x402 (HTTP 402 -> sign -> 200)
|
|
48
|
+
# intel = Intel(api_key=os.environ["INTEL_API_KEY"]) # prepaid pack or Stripe plan
|
|
49
|
+
# intel = Intel() # free trial, 100 calls/day
|
|
50
|
+
|
|
51
|
+
book = ["BTC", "ETH", "NVDA", "MSTR", "CL"]
|
|
52
|
+
|
|
53
|
+
while True:
|
|
54
|
+
p = intel.pulse() # $0.001 — anything new in the last hour?
|
|
55
|
+
if p["high_severity"]:
|
|
56
|
+
for e in intel.events_since(since="4h", universe=book, min_confidence=0.4)["events"]: # $0.005
|
|
57
|
+
for imp in (i for i in e["impacts"] if i["asset_id"] in book and i["confidence"] >= 0.5):
|
|
58
|
+
brief = intel.brief(imp["asset_id"]) # $0.10 — pressure, headlines, filings, derivatives, catalysts
|
|
59
|
+
if not brief["tradable_now"]:
|
|
60
|
+
continue # venue closed -> wait for next_open
|
|
61
|
+
d = intel.derivs_for(imp["asset_id"]) if imp["asset_id"] in ("BTC", "ETH") else None # $0.003 — funding/OI/premium
|
|
62
|
+
print(imp["asset_id"], "LONG" if imp["direction"] > 0 else "SHORT", imp["confidence"], e["title"], d and d["flags"])
|
|
63
|
+
# -> your execution logic here
|
|
64
|
+
time.sleep(3600)
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
Async: `from degenscan_intel import AsyncIntel` — same methods, `await`ed.
|
|
68
|
+
|
|
69
|
+
## Buy a prepaid key with USDC (no human, no card)
|
|
70
|
+
|
|
71
|
+
```python
|
|
72
|
+
intel = Intel(private_key=os.environ["AGENT_WALLET_PK"])
|
|
73
|
+
key = intel.buy_pack("pack_1k")["api_key"] # $5 USDC -> 1,000 calls, lifetime. Also pack_10k ($40), pack_100k ($300)
|
|
74
|
+
cheap = Intel(api_key=key) # no per-call signatures from here on
|
|
75
|
+
cheap.key_status() # {"calls_used": ..., "calls_left": ...}
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
## Methods
|
|
79
|
+
|
|
80
|
+
| Method | REST | Price | Returns |
|
|
81
|
+
|---|---|---|---|
|
|
82
|
+
| `pulse()` | `GET /v1/pulse` | $0.001 | event counts last hour by class, high-severity count, venues open |
|
|
83
|
+
| `events_since(since, universe, min_confidence, limit)` | `GET /v1/events` | $0.005 | events with per-asset impacts, `tradable_now`, `next_open` |
|
|
84
|
+
| `impact_for(asset, since)` | `GET /v1/impact/{asset}` | $0.003 | net bias on one asset + driving events |
|
|
85
|
+
| `exposure_graph(asset, depth)` | `GET /v1/graph/{asset}` | $0.002 | suppliers, countries, commodities, regulators, indices |
|
|
86
|
+
| `regime()` | `GET /v1/regime` | $0.01 | venues open, 24h pressure by asset, top events, prediction markets |
|
|
87
|
+
| `explain(event_id)` | `GET /v1/explain/{id}` | $0.02 | reasoning behind one impact |
|
|
88
|
+
| `polymarket(market)` | `GET /v1/polymarket/{market}` | $0.01 | current odds + primary events that bear on the question |
|
|
89
|
+
| `news_for(ticker)` | `GET /v1/news/{ticker}` | $0.002 | headlines with tier, corroboration, sentiment |
|
|
90
|
+
| `filings_for(ticker, forms=[...])` | `GET /v1/filings/{ticker}` | $0.002 | 8-K, Form 4, 13D/G, S-1 |
|
|
91
|
+
| `calendar(days, types)` | `GET /v1/calendar` | $0.002 | FOMC, CPI, NFP, PCE, GDP, earnings, auctions |
|
|
92
|
+
| `derivs_for(symbol)` | `GET /v1/derivs/{symbol}` | $0.003 | Hyperliquid funding (1h/8h/annualized), predicted funding by venue, OI, premium, 24h volume, flags |
|
|
93
|
+
| `brief(asset)` | `GET /v1/brief/{asset}` | $0.10 | everything above for one asset in one call |
|
|
94
|
+
| `universe()`, `sources()`, `health()`, `plans()`, `packs()` | — | free | coverage, connector status, card plans, USDC packs |
|
|
95
|
+
|
|
96
|
+
Every paid response carries `_billing: {tool, price_usd, method}`; x402 responses also carry `_payment_response` (settlement receipt with tx hash).
|
|
97
|
+
|
|
98
|
+
## How payment works (x402)
|
|
99
|
+
|
|
100
|
+
1. Agent calls a priced route → server answers **HTTP 402** with `PAYMENT-REQUIRED` (USDC on Base `eip155:8453` or Solana, amount, payTo).
|
|
101
|
+
2. The client (Coinbase's `x402` package) signs an EIP-3009 USDC transfer with your wallet — gas is paid by the facilitator (Coinbase CDP / PayAI).
|
|
102
|
+
3. The request is retried with the signature → **200** + data + `PAYMENT-RESPONSE` (tx hash).
|
|
103
|
+
|
|
104
|
+
Use a dedicated agent wallet with a few USDC. Never your main wallet.
|
|
105
|
+
|
|
106
|
+
## Reading the output
|
|
107
|
+
|
|
108
|
+
- `direction`: `1` supportive, `-1` negative, `0` unclear. `confidence` (0..1) = source tier × severity/novelty × graph-path weight — a ranking signal, **not a probability**.
|
|
109
|
+
- `corroboration.count` = independent sources. Primary sources (SEC, Fed, USGS) originate events; media only corroborates.
|
|
110
|
+
- `path` shows the exposure route, e.g. `nat.quake → facility:TSMC-Fab18 → company:TSM → company:NVDA`.
|
|
111
|
+
- `universe_version` is stamped on every response for reproducible backtests.
|
|
112
|
+
|
|
113
|
+
## Also available as
|
|
114
|
+
|
|
115
|
+
- **MCP server** (Claude Code, Cursor, OpenClaw): `{"mcpServers": {"degenscan-intel": {"url": "https://intel.degenscan.io/mcp"}}}`
|
|
116
|
+
- **Agent skill**: `npx skills add tradewr333-lgtm/degenscan-intel`
|
|
117
|
+
- **TypeScript/JavaScript**: `npm i @degenscan/intel`
|
|
118
|
+
- **Public metrics** (paying wallets, tx hashes, operator wallets excluded): `https://intel.degenscan.io/v1/metrics`
|
|
119
|
+
|
|
120
|
+
## Limits
|
|
121
|
+
|
|
122
|
+
US-equity-heavy coverage (top-100 by volume + indices), 15 crypto, main commodities/FX/rates — check `universe()`. No price data, no forecasts. Liquidations are not part of `derivs_for`. Sources marked best-effort in `sources()` may go quiet.
|
|
123
|
+
|
|
124
|
+
MIT © Marbella Collins LLC · contact@degenscan.io
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
# degenscan-intel
|
|
2
|
+
|
|
3
|
+
Market-event intelligence for AI trading agents, paid per call in USDC (x402) or with an API key.
|
|
4
|
+
|
|
5
|
+
One normalized feed of price-moving events from ~40 primary sources — SEC EDGAR (8-K, Form 4, 13D), Federal Reserve, Federal Register, ECB/BoE/BoJ, FTC/DOJ/FDA/CFTC/FCC, USGS earthquakes, NOAA/NHC storms, Nasdaq halts, DefiLlama hacks, Polymarket odds, Hyperliquid perps — scored against an exposure graph into per-asset impacts (`direction`, `confidence`, `path`). Deterministic, sub-200 ms, every event links to its source document.
|
|
6
|
+
|
|
7
|
+
- Service: `https://intel.degenscan.io` · MCP: `POST https://intel.degenscan.io/mcp` · OpenAPI: `/openapi.json` · Docs for LLMs: `/llms.txt`
|
|
8
|
+
- Prices: $0.001–$0.02 per call (brief $0.10). No subscription needed. Free trial: 100 calls/day/IP.
|
|
9
|
+
- Operator: Marbella Collins LLC · MIT · Information and analytics only — not investment advice.
|
|
10
|
+
|
|
11
|
+
## Install
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
pip install degenscan-intel # API key / free trial
|
|
15
|
+
pip install "degenscan-intel[x402]" # + per-call USDC payments from an agent wallet
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## 20-line trading-agent loop
|
|
19
|
+
|
|
20
|
+
```python
|
|
21
|
+
import os, time
|
|
22
|
+
from degenscan_intel import Intel
|
|
23
|
+
|
|
24
|
+
# Pick ONE:
|
|
25
|
+
intel = Intel(private_key=os.environ["AGENT_WALLET_PK"]) # pays USDC on Base per call via x402 (HTTP 402 -> sign -> 200)
|
|
26
|
+
# intel = Intel(api_key=os.environ["INTEL_API_KEY"]) # prepaid pack or Stripe plan
|
|
27
|
+
# intel = Intel() # free trial, 100 calls/day
|
|
28
|
+
|
|
29
|
+
book = ["BTC", "ETH", "NVDA", "MSTR", "CL"]
|
|
30
|
+
|
|
31
|
+
while True:
|
|
32
|
+
p = intel.pulse() # $0.001 — anything new in the last hour?
|
|
33
|
+
if p["high_severity"]:
|
|
34
|
+
for e in intel.events_since(since="4h", universe=book, min_confidence=0.4)["events"]: # $0.005
|
|
35
|
+
for imp in (i for i in e["impacts"] if i["asset_id"] in book and i["confidence"] >= 0.5):
|
|
36
|
+
brief = intel.brief(imp["asset_id"]) # $0.10 — pressure, headlines, filings, derivatives, catalysts
|
|
37
|
+
if not brief["tradable_now"]:
|
|
38
|
+
continue # venue closed -> wait for next_open
|
|
39
|
+
d = intel.derivs_for(imp["asset_id"]) if imp["asset_id"] in ("BTC", "ETH") else None # $0.003 — funding/OI/premium
|
|
40
|
+
print(imp["asset_id"], "LONG" if imp["direction"] > 0 else "SHORT", imp["confidence"], e["title"], d and d["flags"])
|
|
41
|
+
# -> your execution logic here
|
|
42
|
+
time.sleep(3600)
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
Async: `from degenscan_intel import AsyncIntel` — same methods, `await`ed.
|
|
46
|
+
|
|
47
|
+
## Buy a prepaid key with USDC (no human, no card)
|
|
48
|
+
|
|
49
|
+
```python
|
|
50
|
+
intel = Intel(private_key=os.environ["AGENT_WALLET_PK"])
|
|
51
|
+
key = intel.buy_pack("pack_1k")["api_key"] # $5 USDC -> 1,000 calls, lifetime. Also pack_10k ($40), pack_100k ($300)
|
|
52
|
+
cheap = Intel(api_key=key) # no per-call signatures from here on
|
|
53
|
+
cheap.key_status() # {"calls_used": ..., "calls_left": ...}
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
## Methods
|
|
57
|
+
|
|
58
|
+
| Method | REST | Price | Returns |
|
|
59
|
+
|---|---|---|---|
|
|
60
|
+
| `pulse()` | `GET /v1/pulse` | $0.001 | event counts last hour by class, high-severity count, venues open |
|
|
61
|
+
| `events_since(since, universe, min_confidence, limit)` | `GET /v1/events` | $0.005 | events with per-asset impacts, `tradable_now`, `next_open` |
|
|
62
|
+
| `impact_for(asset, since)` | `GET /v1/impact/{asset}` | $0.003 | net bias on one asset + driving events |
|
|
63
|
+
| `exposure_graph(asset, depth)` | `GET /v1/graph/{asset}` | $0.002 | suppliers, countries, commodities, regulators, indices |
|
|
64
|
+
| `regime()` | `GET /v1/regime` | $0.01 | venues open, 24h pressure by asset, top events, prediction markets |
|
|
65
|
+
| `explain(event_id)` | `GET /v1/explain/{id}` | $0.02 | reasoning behind one impact |
|
|
66
|
+
| `polymarket(market)` | `GET /v1/polymarket/{market}` | $0.01 | current odds + primary events that bear on the question |
|
|
67
|
+
| `news_for(ticker)` | `GET /v1/news/{ticker}` | $0.002 | headlines with tier, corroboration, sentiment |
|
|
68
|
+
| `filings_for(ticker, forms=[...])` | `GET /v1/filings/{ticker}` | $0.002 | 8-K, Form 4, 13D/G, S-1 |
|
|
69
|
+
| `calendar(days, types)` | `GET /v1/calendar` | $0.002 | FOMC, CPI, NFP, PCE, GDP, earnings, auctions |
|
|
70
|
+
| `derivs_for(symbol)` | `GET /v1/derivs/{symbol}` | $0.003 | Hyperliquid funding (1h/8h/annualized), predicted funding by venue, OI, premium, 24h volume, flags |
|
|
71
|
+
| `brief(asset)` | `GET /v1/brief/{asset}` | $0.10 | everything above for one asset in one call |
|
|
72
|
+
| `universe()`, `sources()`, `health()`, `plans()`, `packs()` | — | free | coverage, connector status, card plans, USDC packs |
|
|
73
|
+
|
|
74
|
+
Every paid response carries `_billing: {tool, price_usd, method}`; x402 responses also carry `_payment_response` (settlement receipt with tx hash).
|
|
75
|
+
|
|
76
|
+
## How payment works (x402)
|
|
77
|
+
|
|
78
|
+
1. Agent calls a priced route → server answers **HTTP 402** with `PAYMENT-REQUIRED` (USDC on Base `eip155:8453` or Solana, amount, payTo).
|
|
79
|
+
2. The client (Coinbase's `x402` package) signs an EIP-3009 USDC transfer with your wallet — gas is paid by the facilitator (Coinbase CDP / PayAI).
|
|
80
|
+
3. The request is retried with the signature → **200** + data + `PAYMENT-RESPONSE` (tx hash).
|
|
81
|
+
|
|
82
|
+
Use a dedicated agent wallet with a few USDC. Never your main wallet.
|
|
83
|
+
|
|
84
|
+
## Reading the output
|
|
85
|
+
|
|
86
|
+
- `direction`: `1` supportive, `-1` negative, `0` unclear. `confidence` (0..1) = source tier × severity/novelty × graph-path weight — a ranking signal, **not a probability**.
|
|
87
|
+
- `corroboration.count` = independent sources. Primary sources (SEC, Fed, USGS) originate events; media only corroborates.
|
|
88
|
+
- `path` shows the exposure route, e.g. `nat.quake → facility:TSMC-Fab18 → company:TSM → company:NVDA`.
|
|
89
|
+
- `universe_version` is stamped on every response for reproducible backtests.
|
|
90
|
+
|
|
91
|
+
## Also available as
|
|
92
|
+
|
|
93
|
+
- **MCP server** (Claude Code, Cursor, OpenClaw): `{"mcpServers": {"degenscan-intel": {"url": "https://intel.degenscan.io/mcp"}}}`
|
|
94
|
+
- **Agent skill**: `npx skills add tradewr333-lgtm/degenscan-intel`
|
|
95
|
+
- **TypeScript/JavaScript**: `npm i @degenscan/intel`
|
|
96
|
+
- **Public metrics** (paying wallets, tx hashes, operator wallets excluded): `https://intel.degenscan.io/v1/metrics`
|
|
97
|
+
|
|
98
|
+
## Limits
|
|
99
|
+
|
|
100
|
+
US-equity-heavy coverage (top-100 by volume + indices), 15 crypto, main commodities/FX/rates — check `universe()`. No price data, no forecasts. Liquidations are not part of `derivs_for`. Sources marked best-effort in `sources()` may go quiet.
|
|
101
|
+
|
|
102
|
+
MIT © Marbella Collins LLC · contact@degenscan.io
|
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
"""degenscan-intel — client for Degenscan Intel (https://intel.degenscan.io)
|
|
2
|
+
|
|
3
|
+
Cross-asset market-event intelligence for AI trading agents: ~40 primary sources (SEC EDGAR,
|
|
4
|
+
Federal Reserve, Federal Register, ECB/BoE/BoJ, FTC/DOJ/FDA/CFTC, USGS, NOAA, Nasdaq halts,
|
|
5
|
+
DefiLlama, Polymarket, Hyperliquid) normalized into one event schema and scored against an
|
|
6
|
+
exposure graph into per-asset impacts.
|
|
7
|
+
|
|
8
|
+
Three ways to pay, all automatic:
|
|
9
|
+
* ``private_key`` -> pays each call in USDC on Base via x402 (HTTP 402 -> sign -> 200). Needs ``pip install degenscan-intel[x402]``.
|
|
10
|
+
* ``api_key`` -> prepaid pack bought with USDC (``buy_pack``) or a Stripe subscription.
|
|
11
|
+
* ``free_trial`` -> 100 free calls/day per IP (sends ``X-Free-Trial: 1``). Default when nothing else is set.
|
|
12
|
+
|
|
13
|
+
Information and analytics only — not investment advice. Operator: Marbella Collins LLC.
|
|
14
|
+
"""
|
|
15
|
+
from __future__ import annotations
|
|
16
|
+
|
|
17
|
+
import asyncio
|
|
18
|
+
import json
|
|
19
|
+
from typing import Any, Iterable, Optional
|
|
20
|
+
|
|
21
|
+
import httpx
|
|
22
|
+
|
|
23
|
+
__all__ = ["Intel", "AsyncIntel", "IntelError", "__version__"]
|
|
24
|
+
__version__ = "0.1.0"
|
|
25
|
+
DEFAULT_BASE_URL = "https://intel.degenscan.io"
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
class IntelError(Exception):
|
|
29
|
+
def __init__(self, message: str, status: int, body: Any = None):
|
|
30
|
+
super().__init__(message)
|
|
31
|
+
self.status = status
|
|
32
|
+
self.body = body
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def _q(params: dict[str, Any]) -> dict[str, str]:
|
|
36
|
+
out: dict[str, str] = {}
|
|
37
|
+
for k, v in params.items():
|
|
38
|
+
if v is None:
|
|
39
|
+
continue
|
|
40
|
+
out[k] = ",".join(map(str, v)) if isinstance(v, (list, tuple)) else str(v)
|
|
41
|
+
return out
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
class AsyncIntel:
|
|
45
|
+
"""Async client. Use ``Intel`` for a blocking wrapper."""
|
|
46
|
+
|
|
47
|
+
def __init__(self, *, base_url: str = DEFAULT_BASE_URL, private_key: Optional[str] = None, api_key: Optional[str] = None,
|
|
48
|
+
free_trial: Optional[bool] = None, timeout: float = 20.0, client: Optional[httpx.AsyncClient] = None):
|
|
49
|
+
self.base_url = base_url.rstrip("/")
|
|
50
|
+
self.api_key = api_key
|
|
51
|
+
self.private_key = private_key
|
|
52
|
+
self.free_trial = free_trial if free_trial is not None else (not api_key and not private_key)
|
|
53
|
+
self.timeout = timeout
|
|
54
|
+
self._client = client
|
|
55
|
+
|
|
56
|
+
# ---- transport ------------------------------------------------------------------
|
|
57
|
+
async def _http(self) -> httpx.AsyncClient:
|
|
58
|
+
if self._client is not None:
|
|
59
|
+
return self._client
|
|
60
|
+
if not self.private_key:
|
|
61
|
+
self._client = httpx.AsyncClient(timeout=self.timeout)
|
|
62
|
+
return self._client
|
|
63
|
+
try:
|
|
64
|
+
from eth_account import Account
|
|
65
|
+
from x402 import SchemeRegistration, x402ClientConfig
|
|
66
|
+
from x402.http.clients import wrapHttpxWithPaymentFromConfig
|
|
67
|
+
from x402.mechanisms.evm.exact import ExactEvmScheme
|
|
68
|
+
from x402.mechanisms.evm.signers import EthAccountSigner
|
|
69
|
+
except ImportError as e: # pragma: no cover
|
|
70
|
+
raise ImportError("Per-call USDC payments need: pip install 'degenscan-intel[x402]'") from e
|
|
71
|
+
pk = self.private_key.strip()
|
|
72
|
+
if not pk.startswith("0x"):
|
|
73
|
+
pk = "0x" + pk
|
|
74
|
+
account = Account.from_key(pk)
|
|
75
|
+
cfg = x402ClientConfig(schemes=[SchemeRegistration(network="eip155:8453", client=ExactEvmScheme(signer=EthAccountSigner(account)))])
|
|
76
|
+
self._client = wrapHttpxWithPaymentFromConfig(cfg, timeout=self.timeout)
|
|
77
|
+
return self._client
|
|
78
|
+
|
|
79
|
+
def _headers(self, json_body: bool = False) -> dict[str, str]:
|
|
80
|
+
h = {"accept": "application/json", "user-agent": f"degenscan-intel-py/{__version__}"}
|
|
81
|
+
if json_body:
|
|
82
|
+
h["content-type"] = "application/json"
|
|
83
|
+
if self.api_key:
|
|
84
|
+
h["x-api-key"] = self.api_key
|
|
85
|
+
elif self.free_trial and not self.private_key:
|
|
86
|
+
h["x-free-trial"] = "1"
|
|
87
|
+
return h
|
|
88
|
+
|
|
89
|
+
async def request(self, path: str, *, method: str = "GET", query: Optional[dict[str, Any]] = None, body: Any = None) -> Any:
|
|
90
|
+
"""Low-level request. Returns parsed JSON; raises IntelError on non-2xx (including an unpaid 402)."""
|
|
91
|
+
client = await self._http()
|
|
92
|
+
res = await client.request(method, self.base_url + path, params=_q(query or {}), headers=self._headers(body is not None),
|
|
93
|
+
content=json.dumps(body) if body is not None else None)
|
|
94
|
+
try:
|
|
95
|
+
data = res.json() if res.content else None
|
|
96
|
+
except ValueError:
|
|
97
|
+
data = res.text
|
|
98
|
+
if res.status_code >= 400:
|
|
99
|
+
msg = ("Payment required — pass private_key (USDC on Base), api_key, or free_trial=True" if res.status_code == 402
|
|
100
|
+
else (data or {}).get("error", f"HTTP {res.status_code}") if isinstance(data, dict) else f"HTTP {res.status_code}")
|
|
101
|
+
raise IntelError(msg, res.status_code, data)
|
|
102
|
+
pr = res.headers.get("payment-response")
|
|
103
|
+
if pr and isinstance(data, dict):
|
|
104
|
+
data["_payment_response"] = pr
|
|
105
|
+
return data
|
|
106
|
+
|
|
107
|
+
async def aclose(self) -> None:
|
|
108
|
+
if self._client is not None:
|
|
109
|
+
await self._client.aclose()
|
|
110
|
+
|
|
111
|
+
# ---- free -----------------------------------------------------------------------
|
|
112
|
+
async def universe(self): return await self.request("/v1/universe")
|
|
113
|
+
async def sources(self): return await self.request("/v1/sources")
|
|
114
|
+
async def health(self): return await self.request("/health")
|
|
115
|
+
async def plans(self): return await self.request("/v1/plans")
|
|
116
|
+
async def packs(self): return await self.request("/v1/keys/packs")
|
|
117
|
+
|
|
118
|
+
# ---- paid -----------------------------------------------------------------------
|
|
119
|
+
async def pulse(self):
|
|
120
|
+
"""$0.001 — cheapest probe: event counts in the last hour by class + venues open."""
|
|
121
|
+
return await self.request("/v1/pulse")
|
|
122
|
+
|
|
123
|
+
async def events_since(self, since: str = "4h", universe: Optional[Iterable[str]] = None, min_confidence: Optional[float] = None,
|
|
124
|
+
kinds: Optional[Iterable[str]] = None, limit: Optional[int] = None):
|
|
125
|
+
"""$0.005 — all events since `since` touching your universe, with per-asset impacts."""
|
|
126
|
+
return await self.request("/v1/events", query={"since": since, "universe": list(universe) if universe else None,
|
|
127
|
+
"min_confidence": min_confidence, "kinds": list(kinds) if kinds else None, "limit": limit})
|
|
128
|
+
|
|
129
|
+
async def impact_for(self, asset_id: str, since: str = "24h", limit: Optional[int] = None):
|
|
130
|
+
"""$0.003 — net pressure on one asset and the events driving it."""
|
|
131
|
+
return await self.request(f"/v1/impact/{asset_id}", query={"since": since, "limit": limit})
|
|
132
|
+
|
|
133
|
+
async def exposure_graph(self, asset_id: str, depth: int = 2):
|
|
134
|
+
"""$0.002 — second-order exposure graph."""
|
|
135
|
+
return await self.request(f"/v1/graph/{asset_id}", query={"depth": depth})
|
|
136
|
+
|
|
137
|
+
async def regime(self):
|
|
138
|
+
"""$0.01 — venues open, 24h pressure by asset, top events, prediction markets."""
|
|
139
|
+
return await self.request("/v1/regime")
|
|
140
|
+
|
|
141
|
+
async def explain(self, event_id: str):
|
|
142
|
+
"""$0.02 — the reasoning behind one impact."""
|
|
143
|
+
return await self.request(f"/v1/explain/{event_id}")
|
|
144
|
+
|
|
145
|
+
async def polymarket(self, market: str, since: str = "48h", limit: Optional[int] = None):
|
|
146
|
+
"""$0.01 — Polymarket market (id, slug or question) -> odds + primary-source events that bear on it."""
|
|
147
|
+
from urllib.parse import quote
|
|
148
|
+
return await self.request(f"/v1/polymarket/{quote(market, safe='')}", query={"since": since, "limit": limit})
|
|
149
|
+
|
|
150
|
+
async def news_for(self, ticker: str, since: str = "24h", limit: Optional[int] = None):
|
|
151
|
+
"""$0.002 — headlines on one asset with tier, corroboration and heuristic sentiment."""
|
|
152
|
+
return await self.request(f"/v1/news/{ticker}", query={"since": since, "limit": limit})
|
|
153
|
+
|
|
154
|
+
async def filings_for(self, ticker: str, since: str = "7d", forms: Optional[Iterable[str]] = None, limit: Optional[int] = None):
|
|
155
|
+
"""$0.002 — SEC filings (8-K, Form 4, 13D/G, S-1) on one issuer."""
|
|
156
|
+
return await self.request(f"/v1/filings/{ticker}", query={"since": since, "forms": list(forms) if forms else None, "limit": limit})
|
|
157
|
+
|
|
158
|
+
async def calendar(self, days: int = 7, types: Optional[Iterable[str]] = None, universe: Optional[Iterable[str]] = None):
|
|
159
|
+
"""$0.002 — upcoming macro prints, FOMC, earnings, auctions."""
|
|
160
|
+
return await self.request("/v1/calendar", query={"days": days, "types": list(types) if types else None, "universe": list(universe) if universe else None})
|
|
161
|
+
|
|
162
|
+
async def derivs_for(self, symbol: str, since: str = "24h"):
|
|
163
|
+
"""$0.003 — Hyperliquid perp microstructure: funding (1h/8h/annualized), predicted funding by venue, OI, premium, volume, flags + event pressure."""
|
|
164
|
+
return await self.request(f"/v1/derivs/{symbol}", query={"since": since})
|
|
165
|
+
|
|
166
|
+
async def brief(self, asset_id: str, since: str = "24h"):
|
|
167
|
+
"""$0.10 — one-call pre-trade briefing for one asset."""
|
|
168
|
+
return await self.request(f"/v1/brief/{asset_id}", query={"since": since})
|
|
169
|
+
|
|
170
|
+
# ---- keys -----------------------------------------------------------------------
|
|
171
|
+
async def buy_pack(self, pack: str = "pack_1k"):
|
|
172
|
+
"""Buy a prepaid API key with USDC (needs private_key). pack_1k $5 · pack_10k $40 · pack_100k $300 -> {api_key, total_calls}."""
|
|
173
|
+
if not self.private_key and self._client is None:
|
|
174
|
+
raise IntelError("buy_pack needs a paying wallet (private_key) — it is paid in USDC", 400)
|
|
175
|
+
return await self.request(f"/v1/keys/x402/{pack}", method="POST", body={})
|
|
176
|
+
|
|
177
|
+
async def key_status(self):
|
|
178
|
+
if not self.api_key:
|
|
179
|
+
raise IntelError("key_status needs api_key", 400)
|
|
180
|
+
return await self.request("/v1/keys/me")
|
|
181
|
+
|
|
182
|
+
|
|
183
|
+
class Intel:
|
|
184
|
+
"""Blocking client — same methods as AsyncIntel, without ``await``."""
|
|
185
|
+
|
|
186
|
+
def __init__(self, **kwargs: Any):
|
|
187
|
+
self._a = AsyncIntel(**kwargs)
|
|
188
|
+
|
|
189
|
+
def __getattr__(self, name: str):
|
|
190
|
+
attr = getattr(self._a, name)
|
|
191
|
+
if not callable(attr):
|
|
192
|
+
return attr
|
|
193
|
+
|
|
194
|
+
def run(*args: Any, **kw: Any):
|
|
195
|
+
try:
|
|
196
|
+
loop = asyncio.get_running_loop()
|
|
197
|
+
except RuntimeError:
|
|
198
|
+
loop = None
|
|
199
|
+
if loop and loop.is_running():
|
|
200
|
+
raise RuntimeError("Inside an event loop use AsyncIntel and await the call")
|
|
201
|
+
return asyncio.run(attr(*args, **kw))
|
|
202
|
+
return run
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["hatchling"]
|
|
3
|
+
build-backend = "hatchling.build"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "degenscan-intel"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "Cross-asset market-event intelligence for AI trading agents (SEC, Fed, regulators, disasters, halts, hacks, Polymarket, Hyperliquid perps). Pays per call in USDC via x402 or uses an API key."
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
license = { text = "MIT" }
|
|
11
|
+
authors = [{ name = "Marbella Collins LLC", email = "contact@degenscan.io" }]
|
|
12
|
+
requires-python = ">=3.10"
|
|
13
|
+
keywords = ["x402", "ai-agents", "trading-bot", "market-data", "sec-edgar", "federal-reserve", "hyperliquid", "funding-rate", "polymarket", "mcp", "usdc", "base", "market-events", "langchain", "agentkit"]
|
|
14
|
+
classifiers = ["License :: OSI Approved :: MIT License", "Programming Language :: Python :: 3", "Topic :: Office/Business :: Financial", "Intended Audience :: Developers"]
|
|
15
|
+
dependencies = ["httpx>=0.27"]
|
|
16
|
+
|
|
17
|
+
[project.optional-dependencies]
|
|
18
|
+
x402 = ["x402>=2.24", "eth-account>=0.13"]
|
|
19
|
+
|
|
20
|
+
[project.urls]
|
|
21
|
+
Homepage = "https://intel.degenscan.io"
|
|
22
|
+
Documentation = "https://intel.degenscan.io/llms.txt"
|
|
23
|
+
Repository = "https://github.com/tradewr333-lgtm/degenscan-intel"
|
|
24
|
+
|
|
25
|
+
[tool.hatch.build.targets.wheel]
|
|
26
|
+
packages = ["degenscan_intel"]
|