circle-intelligence 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.
- circle_intelligence-0.1.0/PKG-INFO +88 -0
- circle_intelligence-0.1.0/README.md +64 -0
- circle_intelligence-0.1.0/circle_intelligence/__init__.py +670 -0
- circle_intelligence-0.1.0/circle_intelligence.egg-info/PKG-INFO +88 -0
- circle_intelligence-0.1.0/circle_intelligence.egg-info/SOURCES.txt +8 -0
- circle_intelligence-0.1.0/circle_intelligence.egg-info/dependency_links.txt +1 -0
- circle_intelligence-0.1.0/circle_intelligence.egg-info/requires.txt +8 -0
- circle_intelligence-0.1.0/circle_intelligence.egg-info/top_level.txt +1 -0
- circle_intelligence-0.1.0/pyproject.toml +42 -0
- circle_intelligence-0.1.0/setup.cfg +4 -0
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: circle-intelligence
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Python SDK for Circle Intelligence — F.I.R.E. economy real-time signal detection
|
|
5
|
+
Author-email: Circle Intelligence <dev@circle.news>
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://circle.news
|
|
8
|
+
Project-URL: Documentation, https://circle.news/docs
|
|
9
|
+
Project-URL: Repository, https://github.com/Menexus-GmbH/circle_platform_backend
|
|
10
|
+
Keywords: circle,intelligence,fire,signals,knowledge-graph,defi
|
|
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 :: Software Development :: Libraries :: Python Modules
|
|
16
|
+
Requires-Python: >=3.9
|
|
17
|
+
Description-Content-Type: text/markdown
|
|
18
|
+
Requires-Dist: requests>=2.28
|
|
19
|
+
Provides-Extra: wallet
|
|
20
|
+
Requires-Dist: eth-account>=0.10; extra == "wallet"
|
|
21
|
+
Provides-Extra: payment
|
|
22
|
+
Requires-Dist: eth-account>=0.10; extra == "payment"
|
|
23
|
+
Requires-Dist: web3>=6.0; extra == "payment"
|
|
24
|
+
|
|
25
|
+
# Circle Intelligence SDK
|
|
26
|
+
|
|
27
|
+
Python SDK for [Circle Intelligence](https://circle.news) — real-time F.I.R.E. economy signal detection via 7-agent AI cascade.
|
|
28
|
+
|
|
29
|
+
## Install
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
pip install circle-intelligence # core (browsing, search, chat)
|
|
33
|
+
pip install circle-intelligence[wallet] # + wallet authentication
|
|
34
|
+
pip install circle-intelligence[payment] # + USDC payment flow
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## Quick Start
|
|
38
|
+
|
|
39
|
+
```python
|
|
40
|
+
from circle_intelligence import CircleSDK
|
|
41
|
+
|
|
42
|
+
# Free tier — no auth needed
|
|
43
|
+
sdk = CircleSDK("https://circle.news")
|
|
44
|
+
signals = sdk.get_recent_signals(limit=3)
|
|
45
|
+
entities = sdk.get_kg_entities(search="Bitcoin")
|
|
46
|
+
briefs = sdk.get_briefs(limit=5)
|
|
47
|
+
|
|
48
|
+
# Premium tier — with API key
|
|
49
|
+
sdk = CircleSDK("https://circle.news", api_key="circ_your_key")
|
|
50
|
+
results = sdk.search_signals("DeFi bridge exploit")
|
|
51
|
+
analytics = sdk.get_kg_analytics(days=7)
|
|
52
|
+
response = sdk.chat(signal_id=1744, messages=[{"role": "user", "content": "What happened?"}])
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## Features
|
|
56
|
+
|
|
57
|
+
| Feature | Free | Premium |
|
|
58
|
+
|---------|------|---------|
|
|
59
|
+
| Recent signals | 6h delay, 3 max | Real-time, 100 max |
|
|
60
|
+
| Daily briefs | Yes | Yes |
|
|
61
|
+
| Knowledge graph browsing | Yes | Yes |
|
|
62
|
+
| KG analytics + cross-sector | No | Yes |
|
|
63
|
+
| Semantic search | No | Yes |
|
|
64
|
+
| RAG-powered chat | No | Yes |
|
|
65
|
+
| Simulator execution | No | Yes |
|
|
66
|
+
| Research creation | No | Yes |
|
|
67
|
+
| Depth tree details | No | Yes |
|
|
68
|
+
|
|
69
|
+
## Wallet Authentication (for agents)
|
|
70
|
+
|
|
71
|
+
```python
|
|
72
|
+
from eth_account import Account
|
|
73
|
+
from eth_account.messages import encode_defunct
|
|
74
|
+
|
|
75
|
+
private_key = "0xYOUR_PRIVATE_KEY"
|
|
76
|
+
wallet = Account.from_key(private_key).address
|
|
77
|
+
|
|
78
|
+
result = sdk.authenticate(
|
|
79
|
+
wallet_address=wallet,
|
|
80
|
+
sign_fn=lambda msg: Account.sign_message(
|
|
81
|
+
encode_defunct(text=msg), private_key
|
|
82
|
+
).signature.hex(),
|
|
83
|
+
)
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
## Documentation
|
|
87
|
+
|
|
88
|
+
Full API reference and examples at [circle.news/docs](https://circle.news/docs)
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
# Circle Intelligence SDK
|
|
2
|
+
|
|
3
|
+
Python SDK for [Circle Intelligence](https://circle.news) — real-time F.I.R.E. economy signal detection via 7-agent AI cascade.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
pip install circle-intelligence # core (browsing, search, chat)
|
|
9
|
+
pip install circle-intelligence[wallet] # + wallet authentication
|
|
10
|
+
pip install circle-intelligence[payment] # + USDC payment flow
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Quick Start
|
|
14
|
+
|
|
15
|
+
```python
|
|
16
|
+
from circle_intelligence import CircleSDK
|
|
17
|
+
|
|
18
|
+
# Free tier — no auth needed
|
|
19
|
+
sdk = CircleSDK("https://circle.news")
|
|
20
|
+
signals = sdk.get_recent_signals(limit=3)
|
|
21
|
+
entities = sdk.get_kg_entities(search="Bitcoin")
|
|
22
|
+
briefs = sdk.get_briefs(limit=5)
|
|
23
|
+
|
|
24
|
+
# Premium tier — with API key
|
|
25
|
+
sdk = CircleSDK("https://circle.news", api_key="circ_your_key")
|
|
26
|
+
results = sdk.search_signals("DeFi bridge exploit")
|
|
27
|
+
analytics = sdk.get_kg_analytics(days=7)
|
|
28
|
+
response = sdk.chat(signal_id=1744, messages=[{"role": "user", "content": "What happened?"}])
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## Features
|
|
32
|
+
|
|
33
|
+
| Feature | Free | Premium |
|
|
34
|
+
|---------|------|---------|
|
|
35
|
+
| Recent signals | 6h delay, 3 max | Real-time, 100 max |
|
|
36
|
+
| Daily briefs | Yes | Yes |
|
|
37
|
+
| Knowledge graph browsing | Yes | Yes |
|
|
38
|
+
| KG analytics + cross-sector | No | Yes |
|
|
39
|
+
| Semantic search | No | Yes |
|
|
40
|
+
| RAG-powered chat | No | Yes |
|
|
41
|
+
| Simulator execution | No | Yes |
|
|
42
|
+
| Research creation | No | Yes |
|
|
43
|
+
| Depth tree details | No | Yes |
|
|
44
|
+
|
|
45
|
+
## Wallet Authentication (for agents)
|
|
46
|
+
|
|
47
|
+
```python
|
|
48
|
+
from eth_account import Account
|
|
49
|
+
from eth_account.messages import encode_defunct
|
|
50
|
+
|
|
51
|
+
private_key = "0xYOUR_PRIVATE_KEY"
|
|
52
|
+
wallet = Account.from_key(private_key).address
|
|
53
|
+
|
|
54
|
+
result = sdk.authenticate(
|
|
55
|
+
wallet_address=wallet,
|
|
56
|
+
sign_fn=lambda msg: Account.sign_message(
|
|
57
|
+
encode_defunct(text=msg), private_key
|
|
58
|
+
).signature.hex(),
|
|
59
|
+
)
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
## Documentation
|
|
63
|
+
|
|
64
|
+
Full API reference and examples at [circle.news/docs](https://circle.news/docs)
|
|
@@ -0,0 +1,670 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Circle Intelligence SDK — Programmatic access to The Circle's F.I.R.E. intelligence platform.
|
|
3
|
+
|
|
4
|
+
This SDK enables AI agents and developers to do everything a human user can do on circle.news:
|
|
5
|
+
authenticate via wallet, purchase Premium with USDC, browse signals, search, chat, explore
|
|
6
|
+
the knowledge graph, run simulations, and manage research requests.
|
|
7
|
+
|
|
8
|
+
Install:
|
|
9
|
+
pip install circle-intelligence # core
|
|
10
|
+
pip install circle-intelligence[wallet] # + wallet auth
|
|
11
|
+
pip install circle-intelligence[payment] # + USDC payments
|
|
12
|
+
|
|
13
|
+
Usage:
|
|
14
|
+
from circle_intelligence import CircleSDK
|
|
15
|
+
|
|
16
|
+
# Free tier (no auth)
|
|
17
|
+
sdk = CircleSDK("https://circle.news")
|
|
18
|
+
signals = sdk.get_recent_signals(limit=3)
|
|
19
|
+
|
|
20
|
+
# Premium tier (with API key)
|
|
21
|
+
sdk = CircleSDK("https://circle.news", api_key="circ_abc123...")
|
|
22
|
+
results = sdk.search_signals("bitcoin DeFi hack")
|
|
23
|
+
|
|
24
|
+
# Wallet auth flow (for agents with wallet access)
|
|
25
|
+
sdk = CircleSDK("https://circle.news")
|
|
26
|
+
sdk.authenticate(wallet_address="0x...", sign_fn=my_signer)
|
|
27
|
+
"""
|
|
28
|
+
|
|
29
|
+
import time
|
|
30
|
+
import json
|
|
31
|
+
import hashlib
|
|
32
|
+
import hmac
|
|
33
|
+
import base64
|
|
34
|
+
from typing import Optional, Callable, Iterator
|
|
35
|
+
from dataclasses import dataclass
|
|
36
|
+
|
|
37
|
+
import requests
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
# ---------------------------------------------------------------------------
|
|
41
|
+
# Response types
|
|
42
|
+
# ---------------------------------------------------------------------------
|
|
43
|
+
|
|
44
|
+
@dataclass
|
|
45
|
+
class Signal:
|
|
46
|
+
id: int
|
|
47
|
+
headline: str
|
|
48
|
+
sector: str
|
|
49
|
+
confidence: float
|
|
50
|
+
significance: float
|
|
51
|
+
category: str
|
|
52
|
+
timestamp: Optional[str]
|
|
53
|
+
body: Optional[str] = None
|
|
54
|
+
source_url: Optional[str] = None
|
|
55
|
+
source_name: Optional[str] = None
|
|
56
|
+
cascade_trace: Optional[dict] = None
|
|
57
|
+
council_output: Optional[dict] = None
|
|
58
|
+
suggested_market: Optional[str] = None
|
|
59
|
+
parent_signal_id: Optional[int] = None
|
|
60
|
+
research_depth: int = 0
|
|
61
|
+
narrative_durability: float = 0.0
|
|
62
|
+
|
|
63
|
+
@classmethod
|
|
64
|
+
def from_dict(cls, d: dict) -> "Signal":
|
|
65
|
+
return cls(
|
|
66
|
+
id=d.get("id", 0),
|
|
67
|
+
headline=d.get("headline", ""),
|
|
68
|
+
sector=d.get("sector", ""),
|
|
69
|
+
confidence=d.get("confidence", 0),
|
|
70
|
+
significance=d.get("significance", 0),
|
|
71
|
+
category=d.get("category", ""),
|
|
72
|
+
timestamp=d.get("timestamp"),
|
|
73
|
+
body=d.get("body"),
|
|
74
|
+
source_url=d.get("source_url"),
|
|
75
|
+
source_name=d.get("source_name"),
|
|
76
|
+
cascade_trace=d.get("cascade_trace"),
|
|
77
|
+
council_output=d.get("council_output"),
|
|
78
|
+
suggested_market=d.get("suggested_market"),
|
|
79
|
+
parent_signal_id=d.get("parent_signal_id"),
|
|
80
|
+
research_depth=d.get("research_depth", 0),
|
|
81
|
+
narrative_durability=d.get("narrative_durability", 0),
|
|
82
|
+
)
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
@dataclass
|
|
86
|
+
class AuthResult:
|
|
87
|
+
token: str
|
|
88
|
+
wallet: str
|
|
89
|
+
tier: str
|
|
90
|
+
credits_remaining: int
|
|
91
|
+
api_key: Optional[str]
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
@dataclass
|
|
95
|
+
class PaymentResult:
|
|
96
|
+
status: str
|
|
97
|
+
tier: str
|
|
98
|
+
credits: int
|
|
99
|
+
api_key: Optional[str]
|
|
100
|
+
message: str
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
# ---------------------------------------------------------------------------
|
|
104
|
+
# SDK
|
|
105
|
+
# ---------------------------------------------------------------------------
|
|
106
|
+
|
|
107
|
+
class CircleSDK:
|
|
108
|
+
"""
|
|
109
|
+
Circle Intelligence SDK.
|
|
110
|
+
|
|
111
|
+
Supports three access modes:
|
|
112
|
+
1. No auth — free endpoints only (signals with 6h delay, briefs, watchman, KG browsing)
|
|
113
|
+
2. API key — pass api_key="circ_..." for Premium endpoints
|
|
114
|
+
3. Wallet auth — call authenticate() to get JWT, then all endpoints work
|
|
115
|
+
|
|
116
|
+
Args:
|
|
117
|
+
base_url: API base URL (e.g. "https://circle.news" or "http://localhost:8000")
|
|
118
|
+
api_key: Optional Premium API key (circ_... prefix)
|
|
119
|
+
timeout: Request timeout in seconds (default 30)
|
|
120
|
+
"""
|
|
121
|
+
|
|
122
|
+
def __init__(self, base_url: str, api_key: str = "", timeout: int = 30):
|
|
123
|
+
self.base_url = base_url.rstrip("/")
|
|
124
|
+
self.api_key = api_key
|
|
125
|
+
self.timeout = timeout
|
|
126
|
+
self._jwt: Optional[str] = None
|
|
127
|
+
self._wallet: Optional[str] = None
|
|
128
|
+
self._tier: Optional[str] = None
|
|
129
|
+
self._session = requests.Session()
|
|
130
|
+
|
|
131
|
+
# ---------------------------------------------------------------------------
|
|
132
|
+
# Internal helpers
|
|
133
|
+
# ---------------------------------------------------------------------------
|
|
134
|
+
|
|
135
|
+
def _headers(self) -> dict:
|
|
136
|
+
h = {"Content-Type": "application/json"}
|
|
137
|
+
if self.api_key:
|
|
138
|
+
h["X-API-Key"] = self.api_key
|
|
139
|
+
elif self._jwt:
|
|
140
|
+
h["Authorization"] = f"Bearer {self._jwt}"
|
|
141
|
+
return h
|
|
142
|
+
|
|
143
|
+
def _get(self, path: str, params: dict = None) -> dict:
|
|
144
|
+
r = self._session.get(
|
|
145
|
+
f"{self.base_url}{path}",
|
|
146
|
+
headers=self._headers(),
|
|
147
|
+
params=params,
|
|
148
|
+
timeout=self.timeout,
|
|
149
|
+
)
|
|
150
|
+
r.raise_for_status()
|
|
151
|
+
return r.json()
|
|
152
|
+
|
|
153
|
+
def _post(self, path: str, data: dict = None) -> dict:
|
|
154
|
+
r = self._session.post(
|
|
155
|
+
f"{self.base_url}{path}",
|
|
156
|
+
headers=self._headers(),
|
|
157
|
+
json=data,
|
|
158
|
+
timeout=self.timeout,
|
|
159
|
+
)
|
|
160
|
+
r.raise_for_status()
|
|
161
|
+
return r.json()
|
|
162
|
+
|
|
163
|
+
def _post_sse(self, path: str, data: dict) -> Iterator[str]:
|
|
164
|
+
"""POST with SSE streaming response. Yields content tokens."""
|
|
165
|
+
r = self._session.post(
|
|
166
|
+
f"{self.base_url}{path}",
|
|
167
|
+
headers=self._headers(),
|
|
168
|
+
json=data,
|
|
169
|
+
timeout=self.timeout,
|
|
170
|
+
stream=True,
|
|
171
|
+
)
|
|
172
|
+
r.raise_for_status()
|
|
173
|
+
for line in r.iter_lines(decode_unicode=True):
|
|
174
|
+
if line and line.startswith("data: "):
|
|
175
|
+
try:
|
|
176
|
+
payload = json.loads(line[6:])
|
|
177
|
+
if payload.get("content"):
|
|
178
|
+
yield payload["content"]
|
|
179
|
+
except json.JSONDecodeError:
|
|
180
|
+
pass
|
|
181
|
+
|
|
182
|
+
# ---------------------------------------------------------------------------
|
|
183
|
+
# Authentication — wallet-based (for agents with signing capability)
|
|
184
|
+
# ---------------------------------------------------------------------------
|
|
185
|
+
|
|
186
|
+
def authenticate(
|
|
187
|
+
self,
|
|
188
|
+
wallet_address: str,
|
|
189
|
+
sign_fn: Callable[[str], str],
|
|
190
|
+
) -> AuthResult:
|
|
191
|
+
"""
|
|
192
|
+
Authenticate via wallet signature. No passwords, no emails.
|
|
193
|
+
|
|
194
|
+
Args:
|
|
195
|
+
wallet_address: Ethereum/Hedera wallet address (0x...)
|
|
196
|
+
sign_fn: Function that takes a message string and returns hex signature.
|
|
197
|
+
For eth_account: lambda msg: Account.sign_message(
|
|
198
|
+
encode_defunct(text=msg), private_key).signature.hex()
|
|
199
|
+
|
|
200
|
+
Returns:
|
|
201
|
+
AuthResult with JWT token, tier, and credits info.
|
|
202
|
+
|
|
203
|
+
Example:
|
|
204
|
+
from eth_account import Account
|
|
205
|
+
from eth_account.messages import encode_defunct
|
|
206
|
+
|
|
207
|
+
key = "0xYOUR_PRIVATE_KEY"
|
|
208
|
+
sdk.authenticate(
|
|
209
|
+
wallet_address="0x...",
|
|
210
|
+
sign_fn=lambda msg: Account.sign_message(
|
|
211
|
+
encode_defunct(text=msg), key
|
|
212
|
+
).signature.hex()
|
|
213
|
+
)
|
|
214
|
+
"""
|
|
215
|
+
wallet = wallet_address.lower().strip()
|
|
216
|
+
|
|
217
|
+
# Step 1: Get nonce
|
|
218
|
+
nonce_resp = self._get("/api/auth/nonce", params={"wallet": wallet})
|
|
219
|
+
message = nonce_resp["message"]
|
|
220
|
+
|
|
221
|
+
# Step 2: Sign
|
|
222
|
+
signature = sign_fn(message)
|
|
223
|
+
if not signature.startswith("0x"):
|
|
224
|
+
signature = "0x" + signature
|
|
225
|
+
|
|
226
|
+
# Step 3: Verify
|
|
227
|
+
verify_resp = self._post("/api/auth/verify", {
|
|
228
|
+
"wallet_address": wallet,
|
|
229
|
+
"signature": signature,
|
|
230
|
+
"message": message,
|
|
231
|
+
})
|
|
232
|
+
|
|
233
|
+
self._jwt = verify_resp["token"]
|
|
234
|
+
self._wallet = wallet
|
|
235
|
+
self._tier = verify_resp.get("tier", "free")
|
|
236
|
+
|
|
237
|
+
return AuthResult(
|
|
238
|
+
token=verify_resp["token"],
|
|
239
|
+
wallet=wallet,
|
|
240
|
+
tier=verify_resp.get("tier", "free"),
|
|
241
|
+
credits_remaining=verify_resp.get("credits_remaining", 0),
|
|
242
|
+
api_key=verify_resp.get("api_key"),
|
|
243
|
+
)
|
|
244
|
+
|
|
245
|
+
def refresh_token(self) -> str:
|
|
246
|
+
"""Refresh JWT token before it expires (24h default TTL)."""
|
|
247
|
+
resp = self._post("/api/auth/refresh")
|
|
248
|
+
self._jwt = resp["token"]
|
|
249
|
+
return resp["token"]
|
|
250
|
+
|
|
251
|
+
# ---------------------------------------------------------------------------
|
|
252
|
+
# Payments — USDC on Hedera
|
|
253
|
+
# ---------------------------------------------------------------------------
|
|
254
|
+
|
|
255
|
+
def get_payment_config(self) -> dict:
|
|
256
|
+
"""Get payment configuration: receiving wallet, chain, tier pricing."""
|
|
257
|
+
return self._get("/api/payments/config")
|
|
258
|
+
|
|
259
|
+
def submit_payment(self, tx_hash: str, tier: str = "premium") -> PaymentResult:
|
|
260
|
+
"""
|
|
261
|
+
Submit a USDC payment transaction hash for on-chain verification.
|
|
262
|
+
|
|
263
|
+
After sending USDC to the receiving wallet on Hedera, call this to verify
|
|
264
|
+
and activate the Premium tier.
|
|
265
|
+
|
|
266
|
+
Args:
|
|
267
|
+
tx_hash: Hedera transaction hash (0x...)
|
|
268
|
+
tier: "premium" (only option)
|
|
269
|
+
|
|
270
|
+
Returns:
|
|
271
|
+
PaymentResult with tier, credits, and API key (on first payment).
|
|
272
|
+
"""
|
|
273
|
+
resp = self._post("/api/payments/submit", {
|
|
274
|
+
"tx_hash": tx_hash,
|
|
275
|
+
"tier": tier,
|
|
276
|
+
})
|
|
277
|
+
# Store the API key if returned
|
|
278
|
+
if resp.get("api_key"):
|
|
279
|
+
self.api_key = resp["api_key"]
|
|
280
|
+
return PaymentResult(
|
|
281
|
+
status=resp["status"],
|
|
282
|
+
tier=resp["tier"],
|
|
283
|
+
credits=resp["credits"],
|
|
284
|
+
api_key=resp.get("api_key"),
|
|
285
|
+
message=resp["message"],
|
|
286
|
+
)
|
|
287
|
+
|
|
288
|
+
def get_usage(self) -> dict:
|
|
289
|
+
"""Get API usage stats: credits, burn rate, daily/hourly breakdown."""
|
|
290
|
+
return self._get("/api/payments/usage")
|
|
291
|
+
|
|
292
|
+
def get_payment_history(self) -> list:
|
|
293
|
+
"""Get payment transaction history."""
|
|
294
|
+
return self._get("/api/payments/history")
|
|
295
|
+
|
|
296
|
+
# ---------------------------------------------------------------------------
|
|
297
|
+
# API Key management
|
|
298
|
+
# ---------------------------------------------------------------------------
|
|
299
|
+
|
|
300
|
+
def get_me(self) -> dict:
|
|
301
|
+
"""Get current authenticated user profile."""
|
|
302
|
+
return self._get("/api/auth/me")
|
|
303
|
+
|
|
304
|
+
def generate_api_key(self) -> str:
|
|
305
|
+
"""Generate a new API key (Premium tier required). Returns the key string."""
|
|
306
|
+
resp = self._post("/api/auth/generate-key")
|
|
307
|
+
key = resp["api_key"]
|
|
308
|
+
self.api_key = key
|
|
309
|
+
return key
|
|
310
|
+
|
|
311
|
+
def revoke_api_key(self) -> dict:
|
|
312
|
+
"""Revoke the current API key."""
|
|
313
|
+
resp = self._post("/api/auth/revoke-key")
|
|
314
|
+
self.api_key = ""
|
|
315
|
+
return resp
|
|
316
|
+
|
|
317
|
+
# ---------------------------------------------------------------------------
|
|
318
|
+
# Signals — the core intelligence feed
|
|
319
|
+
# ---------------------------------------------------------------------------
|
|
320
|
+
|
|
321
|
+
def get_recent_signals(
|
|
322
|
+
self, limit: int = 20, offset: int = 0, sector: str = "", category: str = ""
|
|
323
|
+
) -> dict:
|
|
324
|
+
"""
|
|
325
|
+
Get recent published signals.
|
|
326
|
+
|
|
327
|
+
Free tier: 6-hour delay, max 3 per request.
|
|
328
|
+
Premium: real-time, up to 100 per request.
|
|
329
|
+
|
|
330
|
+
Args:
|
|
331
|
+
limit: Number of signals (1-100)
|
|
332
|
+
offset: Pagination offset
|
|
333
|
+
sector: Filter by F.I.R.E. sector (finance, insurance, real_infrastructure, electronic_labour)
|
|
334
|
+
category: "signal" (niche early detection) or "news" (mainstream)
|
|
335
|
+
|
|
336
|
+
Returns:
|
|
337
|
+
Dict with signals[], total, limit, offset, delayed, delay_hours
|
|
338
|
+
"""
|
|
339
|
+
params = {"limit": limit, "offset": offset}
|
|
340
|
+
if sector:
|
|
341
|
+
params["sector"] = sector
|
|
342
|
+
if category:
|
|
343
|
+
params["category"] = category
|
|
344
|
+
return self._get("/api/signals/recent", params)
|
|
345
|
+
|
|
346
|
+
def get_signal(self, signal_id: int) -> Signal:
|
|
347
|
+
"""Get full signal details including cascade trace and council analysis."""
|
|
348
|
+
data = self._get(f"/api/signals/{signal_id}")
|
|
349
|
+
return Signal.from_dict(data)
|
|
350
|
+
|
|
351
|
+
def get_related_signals(self, signal_id: int, limit: int = 4) -> list[dict]:
|
|
352
|
+
"""Get semantically related signals via pgvector cosine similarity."""
|
|
353
|
+
resp = self._get(f"/api/signals/{signal_id}/related", {"limit": limit})
|
|
354
|
+
return resp.get("signals", [])
|
|
355
|
+
|
|
356
|
+
def search_signals(self, query: str, limit: int = 10, sector: str = "") -> dict:
|
|
357
|
+
"""
|
|
358
|
+
Semantic search over signals (Premium required).
|
|
359
|
+
|
|
360
|
+
Uses hybrid pgvector + knowledge graph retrieval.
|
|
361
|
+
|
|
362
|
+
Args:
|
|
363
|
+
query: Natural language search query
|
|
364
|
+
limit: Max results (1-20)
|
|
365
|
+
sector: Optional sector filter
|
|
366
|
+
|
|
367
|
+
Returns:
|
|
368
|
+
Dict with signals[] (includes relevance_score), total, query
|
|
369
|
+
"""
|
|
370
|
+
params = {"q": query, "limit": limit}
|
|
371
|
+
if sector:
|
|
372
|
+
params["sector"] = sector
|
|
373
|
+
return self._get("/api/signals/search", params)
|
|
374
|
+
|
|
375
|
+
def get_signal_feed(self, limit: int = 20, offset: int = 0, sector: str = "") -> dict:
|
|
376
|
+
"""Get niche signal feed (web search, 4chan, RSS — excludes mainstream news)."""
|
|
377
|
+
params = {"limit": limit, "offset": offset}
|
|
378
|
+
if sector:
|
|
379
|
+
params["sector"] = sector
|
|
380
|
+
return self._get("/api/signals/feed", params)
|
|
381
|
+
|
|
382
|
+
# ---------------------------------------------------------------------------
|
|
383
|
+
# Chat — RAG-powered Q&A grounded in verified intelligence
|
|
384
|
+
# ---------------------------------------------------------------------------
|
|
385
|
+
|
|
386
|
+
def chat(
|
|
387
|
+
self,
|
|
388
|
+
signal_id: int,
|
|
389
|
+
messages: list[dict],
|
|
390
|
+
signal_text: str = "",
|
|
391
|
+
) -> str:
|
|
392
|
+
"""
|
|
393
|
+
Ask a question about a signal (Premium required).
|
|
394
|
+
|
|
395
|
+
The response is grounded in Circle's verified intelligence database via
|
|
396
|
+
hybrid RAG (pgvector semantic search + knowledge graph traversal).
|
|
397
|
+
|
|
398
|
+
Args:
|
|
399
|
+
signal_id: The signal to ask about
|
|
400
|
+
messages: Conversation history [{"role": "user", "content": "..."}, ...]
|
|
401
|
+
signal_text: Fallback signal text (server fetches verified signal by ID)
|
|
402
|
+
|
|
403
|
+
Returns:
|
|
404
|
+
Complete response text.
|
|
405
|
+
|
|
406
|
+
Example:
|
|
407
|
+
response = sdk.chat(
|
|
408
|
+
signal_id=1744,
|
|
409
|
+
messages=[{"role": "user", "content": "What related DeFi hacks has Circle documented?"}]
|
|
410
|
+
)
|
|
411
|
+
"""
|
|
412
|
+
tokens = list(self.chat_stream(signal_id, messages, signal_text))
|
|
413
|
+
return "".join(tokens)
|
|
414
|
+
|
|
415
|
+
def chat_stream(
|
|
416
|
+
self,
|
|
417
|
+
signal_id: int,
|
|
418
|
+
messages: list[dict],
|
|
419
|
+
signal_text: str = "",
|
|
420
|
+
) -> Iterator[str]:
|
|
421
|
+
"""
|
|
422
|
+
Streaming version of chat(). Yields tokens as they arrive via SSE.
|
|
423
|
+
|
|
424
|
+
Args:
|
|
425
|
+
signal_id: The signal to ask about
|
|
426
|
+
messages: Conversation history
|
|
427
|
+
signal_text: Fallback signal text
|
|
428
|
+
|
|
429
|
+
Yields:
|
|
430
|
+
String tokens as they stream from the server.
|
|
431
|
+
"""
|
|
432
|
+
yield from self._post_sse("/api/chat", {
|
|
433
|
+
"signalId": signal_id,
|
|
434
|
+
"signalText": signal_text,
|
|
435
|
+
"messages": messages,
|
|
436
|
+
})
|
|
437
|
+
|
|
438
|
+
# ---------------------------------------------------------------------------
|
|
439
|
+
# Knowledge Graph — entity relationships and intelligence analytics
|
|
440
|
+
# ---------------------------------------------------------------------------
|
|
441
|
+
|
|
442
|
+
def get_kg_entities(
|
|
443
|
+
self, sector: str = "", type: str = "", limit: int = 100, search: str = ""
|
|
444
|
+
) -> dict:
|
|
445
|
+
"""Browse knowledge graph entities with optional filters."""
|
|
446
|
+
params = {"limit": limit}
|
|
447
|
+
if sector:
|
|
448
|
+
params["sector"] = sector
|
|
449
|
+
if type:
|
|
450
|
+
params["type"] = type
|
|
451
|
+
if search:
|
|
452
|
+
params["search"] = search
|
|
453
|
+
return self._get("/api/knowledge-graph/entities", params)
|
|
454
|
+
|
|
455
|
+
def get_kg_entity(self, entity_id: int) -> dict:
|
|
456
|
+
"""Get entity detail with connected edges and recent signal mentions."""
|
|
457
|
+
return self._get(f"/api/knowledge-graph/entity/{entity_id}")
|
|
458
|
+
|
|
459
|
+
def get_kg_graph(
|
|
460
|
+
self, sector: str = "", min_weight: int = 1, limit: int = 500,
|
|
461
|
+
from_date: str = "", to_date: str = ""
|
|
462
|
+
) -> dict:
|
|
463
|
+
"""Get D3-compatible graph data (nodes + links) with optional time filtering."""
|
|
464
|
+
params = {"min_weight": min_weight, "limit": limit}
|
|
465
|
+
if sector:
|
|
466
|
+
params["sector"] = sector
|
|
467
|
+
if from_date:
|
|
468
|
+
params["from_date"] = from_date
|
|
469
|
+
if to_date:
|
|
470
|
+
params["to_date"] = to_date
|
|
471
|
+
return self._get("/api/knowledge-graph/graph", params)
|
|
472
|
+
|
|
473
|
+
def get_kg_neighborhood(
|
|
474
|
+
self, entity_id: int, depth: int = 1, from_date: str = "", to_date: str = ""
|
|
475
|
+
) -> dict:
|
|
476
|
+
"""Get entity and its N-hop connections as a graph."""
|
|
477
|
+
params = {"depth": depth}
|
|
478
|
+
if from_date:
|
|
479
|
+
params["from_date"] = from_date
|
|
480
|
+
if to_date:
|
|
481
|
+
params["to_date"] = to_date
|
|
482
|
+
return self._get(f"/api/knowledge-graph/neighborhood/{entity_id}", params)
|
|
483
|
+
|
|
484
|
+
def get_kg_cross_sector(self) -> dict:
|
|
485
|
+
"""Get entities appearing in 2+ F.I.R.E. sectors (Premium required)."""
|
|
486
|
+
return self._get("/api/knowledge-graph/cross-sector")
|
|
487
|
+
|
|
488
|
+
def get_kg_analytics(self, days: int = 7) -> dict:
|
|
489
|
+
"""
|
|
490
|
+
Get intelligence analytics (Premium required).
|
|
491
|
+
|
|
492
|
+
Returns trending entities, emerging connections, ecotone entities
|
|
493
|
+
(cross-sector bridges), and fading connections.
|
|
494
|
+
"""
|
|
495
|
+
return self._get("/api/knowledge-graph/analytics", {"days": days})
|
|
496
|
+
|
|
497
|
+
# ---------------------------------------------------------------------------
|
|
498
|
+
# Research — community-driven deep investigation
|
|
499
|
+
# ---------------------------------------------------------------------------
|
|
500
|
+
|
|
501
|
+
def list_research_requests(self) -> list:
|
|
502
|
+
"""List all community research requests with progress metrics."""
|
|
503
|
+
return self._get("/api/research/requests")
|
|
504
|
+
|
|
505
|
+
def get_research_request(self, request_id: int) -> dict:
|
|
506
|
+
"""Get single research request with details."""
|
|
507
|
+
return self._get(f"/api/research/{request_id}")
|
|
508
|
+
|
|
509
|
+
def create_research_request(
|
|
510
|
+
self, topic: str, description: str = "", provider: str = "",
|
|
511
|
+
api_key: str = "", model_hint: str = "", **vmosk
|
|
512
|
+
) -> dict:
|
|
513
|
+
"""
|
|
514
|
+
Create a community research request (Premium required).
|
|
515
|
+
|
|
516
|
+
The Circle's cascade will investigate this topic using donated API keys.
|
|
517
|
+
|
|
518
|
+
Args:
|
|
519
|
+
topic: What to research (e.g. "DeFi insurance protocols on Solana")
|
|
520
|
+
description: Detailed description of what to investigate
|
|
521
|
+
provider: API key provider (groq, openrouter, anthropic, etc.)
|
|
522
|
+
api_key: Optional API key to donate for this research
|
|
523
|
+
model_hint: Optional model preference
|
|
524
|
+
**vmosk: Optional VMOSK framework fields (vision, mission, objectives, strategies, kpis)
|
|
525
|
+
"""
|
|
526
|
+
body = {
|
|
527
|
+
"topic": topic,
|
|
528
|
+
"description": description,
|
|
529
|
+
"provider": provider,
|
|
530
|
+
"api_key": api_key,
|
|
531
|
+
"model_hint": model_hint,
|
|
532
|
+
}
|
|
533
|
+
for field in ("vision", "mission", "objectives", "strategies", "kpis"):
|
|
534
|
+
if field in vmosk:
|
|
535
|
+
body[field] = vmosk[field]
|
|
536
|
+
return self._post("/api/research/request", body)
|
|
537
|
+
|
|
538
|
+
def get_research_signals(self, request_id: int, limit: int = 50) -> dict:
|
|
539
|
+
"""Get completed signals found by a research request (Premium required)."""
|
|
540
|
+
return self._get(f"/api/research/{request_id}/signals", {"limit": limit})
|
|
541
|
+
|
|
542
|
+
# ---------------------------------------------------------------------------
|
|
543
|
+
# Depth Trees — recursive intelligence
|
|
544
|
+
# ---------------------------------------------------------------------------
|
|
545
|
+
|
|
546
|
+
def list_depth_trees(self, status: str = "active", limit: int = 20) -> dict:
|
|
547
|
+
"""List depth research trees with stats."""
|
|
548
|
+
return self._get("/api/enrichment/depth-trees", {"status": status, "limit": limit})
|
|
549
|
+
|
|
550
|
+
def get_depth_tree(self, tree_id: int) -> dict:
|
|
551
|
+
"""Get full depth research tree with all child signals (Premium required)."""
|
|
552
|
+
return self._get(f"/api/enrichment/depth-trees/{tree_id}")
|
|
553
|
+
|
|
554
|
+
def get_signal_enrichment(self, signal_id: int) -> dict:
|
|
555
|
+
"""Get all enrichment verdicts and consensus for a signal (Premium required)."""
|
|
556
|
+
return self._get(f"/api/enrichment/signal/{signal_id}")
|
|
557
|
+
|
|
558
|
+
# ---------------------------------------------------------------------------
|
|
559
|
+
# Simulator — probability market scenarios
|
|
560
|
+
# ---------------------------------------------------------------------------
|
|
561
|
+
|
|
562
|
+
def list_scenarios(self) -> dict:
|
|
563
|
+
"""List available simulation scenarios."""
|
|
564
|
+
return self._get("/api/simulator/scenarios")
|
|
565
|
+
|
|
566
|
+
def run_simulation(self, scenario: str, params: dict = None) -> dict:
|
|
567
|
+
"""
|
|
568
|
+
Run a market simulation (Premium required).
|
|
569
|
+
|
|
570
|
+
Args:
|
|
571
|
+
scenario: Scenario ID from list_scenarios()
|
|
572
|
+
params: Optional overrides (initial_liquidity_yes/no, trading_rounds, fee_bps)
|
|
573
|
+
"""
|
|
574
|
+
return self._post("/api/simulator/run", {
|
|
575
|
+
"scenario": scenario,
|
|
576
|
+
"params": params or {},
|
|
577
|
+
})
|
|
578
|
+
|
|
579
|
+
# ---------------------------------------------------------------------------
|
|
580
|
+
# Cascade
|
|
581
|
+
# ---------------------------------------------------------------------------
|
|
582
|
+
|
|
583
|
+
def get_metrics(self) -> dict:
|
|
584
|
+
"""Get cascade performance metrics (throughput, rejection rates, sectors)."""
|
|
585
|
+
return self._get("/api/metrics")
|
|
586
|
+
|
|
587
|
+
def run_cascade_demo(self) -> dict:
|
|
588
|
+
"""Run cascade demo on a recent signal with timing breakdown (Premium required)."""
|
|
589
|
+
return self._post("/api/cascade/demo")
|
|
590
|
+
|
|
591
|
+
def get_cascade_visualization(self) -> dict:
|
|
592
|
+
"""Get ASCII diagram of the 7-agent cascade architecture."""
|
|
593
|
+
return self._get("/api/cascade/visualize")
|
|
594
|
+
|
|
595
|
+
# ---------------------------------------------------------------------------
|
|
596
|
+
# Briefs — daily intelligence summaries
|
|
597
|
+
# ---------------------------------------------------------------------------
|
|
598
|
+
|
|
599
|
+
def get_briefs(self, limit: int = 30) -> list:
|
|
600
|
+
"""Get recent daily briefs."""
|
|
601
|
+
return self._get("/api/briefs", {"limit": limit})
|
|
602
|
+
|
|
603
|
+
def get_brief(self, date: str) -> dict:
|
|
604
|
+
"""Get brief for a specific date (ISO format: YYYY-MM-DD)."""
|
|
605
|
+
return self._get(f"/api/briefs/{date}")
|
|
606
|
+
|
|
607
|
+
# ---------------------------------------------------------------------------
|
|
608
|
+
# Watchman — detection accuracy tracking
|
|
609
|
+
# ---------------------------------------------------------------------------
|
|
610
|
+
|
|
611
|
+
def get_watchman(self) -> dict:
|
|
612
|
+
"""Get current watchman accuracy status."""
|
|
613
|
+
return self._get("/api/watchman")
|
|
614
|
+
|
|
615
|
+
def get_watchman_metrics(self) -> dict:
|
|
616
|
+
"""Get detailed watchman metrics."""
|
|
617
|
+
return self._get("/api/watchman/metrics")
|
|
618
|
+
|
|
619
|
+
def get_watchman_history(self, days: int = 90) -> list:
|
|
620
|
+
"""Get historical accuracy trend."""
|
|
621
|
+
resp = self._get("/api/watchman/history", {"days": days})
|
|
622
|
+
return resp.get("history", [])
|
|
623
|
+
|
|
624
|
+
def get_gate_b(self) -> dict:
|
|
625
|
+
"""Check Gate B status (21-day accuracy threshold)."""
|
|
626
|
+
return self._get("/api/watchman/gate-b")
|
|
627
|
+
|
|
628
|
+
# ---------------------------------------------------------------------------
|
|
629
|
+
# Key Donation — contribute API keys to the community pool
|
|
630
|
+
# ---------------------------------------------------------------------------
|
|
631
|
+
|
|
632
|
+
def donate_key(self, provider: str, key: str, model_hint: str = "") -> dict:
|
|
633
|
+
"""
|
|
634
|
+
Donate an API key to Circle's processing pool.
|
|
635
|
+
|
|
636
|
+
Donated keys power the cascade, research, and enrichment engines.
|
|
637
|
+
|
|
638
|
+
Args:
|
|
639
|
+
provider: Key provider (groq, openrouter, anthropic, cerebras, sambanova, etc.)
|
|
640
|
+
key: The API key
|
|
641
|
+
model_hint: Optional model preference
|
|
642
|
+
|
|
643
|
+
Returns:
|
|
644
|
+
Dict with status, donor_hash (save this to track your key)
|
|
645
|
+
"""
|
|
646
|
+
return self._post("/api/keys/donate", {
|
|
647
|
+
"provider": provider,
|
|
648
|
+
"key": key,
|
|
649
|
+
"model_hint": model_hint,
|
|
650
|
+
})
|
|
651
|
+
|
|
652
|
+
def get_key_status(self, donor_hash: str) -> dict:
|
|
653
|
+
"""Check status of a donated key by its donor hash."""
|
|
654
|
+
return self._get(f"/api/keys/status/{donor_hash}")
|
|
655
|
+
|
|
656
|
+
def get_key_pool_stats(self) -> dict:
|
|
657
|
+
"""Get public key pool statistics."""
|
|
658
|
+
return self._get("/api/keys/pool/stats")
|
|
659
|
+
|
|
660
|
+
# ---------------------------------------------------------------------------
|
|
661
|
+
# Utility
|
|
662
|
+
# ---------------------------------------------------------------------------
|
|
663
|
+
|
|
664
|
+
@property
|
|
665
|
+
def is_authenticated(self) -> bool:
|
|
666
|
+
return bool(self._jwt or self.api_key)
|
|
667
|
+
|
|
668
|
+
@property
|
|
669
|
+
def tier(self) -> str:
|
|
670
|
+
return self._tier or ("premium" if self.api_key else "free")
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: circle-intelligence
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Python SDK for Circle Intelligence — F.I.R.E. economy real-time signal detection
|
|
5
|
+
Author-email: Circle Intelligence <dev@circle.news>
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://circle.news
|
|
8
|
+
Project-URL: Documentation, https://circle.news/docs
|
|
9
|
+
Project-URL: Repository, https://github.com/Menexus-GmbH/circle_platform_backend
|
|
10
|
+
Keywords: circle,intelligence,fire,signals,knowledge-graph,defi
|
|
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 :: Software Development :: Libraries :: Python Modules
|
|
16
|
+
Requires-Python: >=3.9
|
|
17
|
+
Description-Content-Type: text/markdown
|
|
18
|
+
Requires-Dist: requests>=2.28
|
|
19
|
+
Provides-Extra: wallet
|
|
20
|
+
Requires-Dist: eth-account>=0.10; extra == "wallet"
|
|
21
|
+
Provides-Extra: payment
|
|
22
|
+
Requires-Dist: eth-account>=0.10; extra == "payment"
|
|
23
|
+
Requires-Dist: web3>=6.0; extra == "payment"
|
|
24
|
+
|
|
25
|
+
# Circle Intelligence SDK
|
|
26
|
+
|
|
27
|
+
Python SDK for [Circle Intelligence](https://circle.news) — real-time F.I.R.E. economy signal detection via 7-agent AI cascade.
|
|
28
|
+
|
|
29
|
+
## Install
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
pip install circle-intelligence # core (browsing, search, chat)
|
|
33
|
+
pip install circle-intelligence[wallet] # + wallet authentication
|
|
34
|
+
pip install circle-intelligence[payment] # + USDC payment flow
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## Quick Start
|
|
38
|
+
|
|
39
|
+
```python
|
|
40
|
+
from circle_intelligence import CircleSDK
|
|
41
|
+
|
|
42
|
+
# Free tier — no auth needed
|
|
43
|
+
sdk = CircleSDK("https://circle.news")
|
|
44
|
+
signals = sdk.get_recent_signals(limit=3)
|
|
45
|
+
entities = sdk.get_kg_entities(search="Bitcoin")
|
|
46
|
+
briefs = sdk.get_briefs(limit=5)
|
|
47
|
+
|
|
48
|
+
# Premium tier — with API key
|
|
49
|
+
sdk = CircleSDK("https://circle.news", api_key="circ_your_key")
|
|
50
|
+
results = sdk.search_signals("DeFi bridge exploit")
|
|
51
|
+
analytics = sdk.get_kg_analytics(days=7)
|
|
52
|
+
response = sdk.chat(signal_id=1744, messages=[{"role": "user", "content": "What happened?"}])
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## Features
|
|
56
|
+
|
|
57
|
+
| Feature | Free | Premium |
|
|
58
|
+
|---------|------|---------|
|
|
59
|
+
| Recent signals | 6h delay, 3 max | Real-time, 100 max |
|
|
60
|
+
| Daily briefs | Yes | Yes |
|
|
61
|
+
| Knowledge graph browsing | Yes | Yes |
|
|
62
|
+
| KG analytics + cross-sector | No | Yes |
|
|
63
|
+
| Semantic search | No | Yes |
|
|
64
|
+
| RAG-powered chat | No | Yes |
|
|
65
|
+
| Simulator execution | No | Yes |
|
|
66
|
+
| Research creation | No | Yes |
|
|
67
|
+
| Depth tree details | No | Yes |
|
|
68
|
+
|
|
69
|
+
## Wallet Authentication (for agents)
|
|
70
|
+
|
|
71
|
+
```python
|
|
72
|
+
from eth_account import Account
|
|
73
|
+
from eth_account.messages import encode_defunct
|
|
74
|
+
|
|
75
|
+
private_key = "0xYOUR_PRIVATE_KEY"
|
|
76
|
+
wallet = Account.from_key(private_key).address
|
|
77
|
+
|
|
78
|
+
result = sdk.authenticate(
|
|
79
|
+
wallet_address=wallet,
|
|
80
|
+
sign_fn=lambda msg: Account.sign_message(
|
|
81
|
+
encode_defunct(text=msg), private_key
|
|
82
|
+
).signature.hex(),
|
|
83
|
+
)
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
## Documentation
|
|
87
|
+
|
|
88
|
+
Full API reference and examples at [circle.news/docs](https://circle.news/docs)
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
README.md
|
|
2
|
+
pyproject.toml
|
|
3
|
+
circle_intelligence/__init__.py
|
|
4
|
+
circle_intelligence.egg-info/PKG-INFO
|
|
5
|
+
circle_intelligence.egg-info/SOURCES.txt
|
|
6
|
+
circle_intelligence.egg-info/dependency_links.txt
|
|
7
|
+
circle_intelligence.egg-info/requires.txt
|
|
8
|
+
circle_intelligence.egg-info/top_level.txt
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
circle_intelligence
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=68.0", "wheel"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "circle-intelligence"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "Python SDK for Circle Intelligence — F.I.R.E. economy real-time signal detection"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
license = {text = "MIT"}
|
|
11
|
+
requires-python = ">=3.9"
|
|
12
|
+
authors = [
|
|
13
|
+
{name = "Circle Intelligence", email = "dev@circle.news"},
|
|
14
|
+
]
|
|
15
|
+
keywords = ["circle", "intelligence", "fire", "signals", "knowledge-graph", "defi"]
|
|
16
|
+
classifiers = [
|
|
17
|
+
"Development Status :: 4 - Beta",
|
|
18
|
+
"Intended Audience :: Developers",
|
|
19
|
+
"License :: OSI Approved :: MIT License",
|
|
20
|
+
"Programming Language :: Python :: 3",
|
|
21
|
+
"Topic :: Software Development :: Libraries :: Python Modules",
|
|
22
|
+
]
|
|
23
|
+
dependencies = [
|
|
24
|
+
"requests>=2.28",
|
|
25
|
+
]
|
|
26
|
+
|
|
27
|
+
[project.optional-dependencies]
|
|
28
|
+
wallet = [
|
|
29
|
+
"eth-account>=0.10",
|
|
30
|
+
]
|
|
31
|
+
payment = [
|
|
32
|
+
"eth-account>=0.10",
|
|
33
|
+
"web3>=6.0",
|
|
34
|
+
]
|
|
35
|
+
|
|
36
|
+
[project.urls]
|
|
37
|
+
Homepage = "https://circle.news"
|
|
38
|
+
Documentation = "https://circle.news/docs"
|
|
39
|
+
Repository = "https://github.com/Menexus-GmbH/circle_platform_backend"
|
|
40
|
+
|
|
41
|
+
[tool.setuptools]
|
|
42
|
+
packages = ["circle_intelligence"]
|