fere-sdk 0.3.1.dev27__tar.gz → 0.4.0.dev29__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.
- {fere_sdk-0.3.1.dev27 → fere_sdk-0.4.0.dev29}/PKG-INFO +1 -1
- {fere_sdk-0.3.1.dev27 → fere_sdk-0.4.0.dev29}/pyproject.toml +1 -1
- {fere_sdk-0.3.1.dev27 → fere_sdk-0.4.0.dev29}/src/fere_sdk/client.py +25 -0
- {fere_sdk-0.3.1.dev27 → fere_sdk-0.4.0.dev29}/src/fere_sdk/low_level.py +47 -0
- {fere_sdk-0.3.1.dev27 → fere_sdk-0.4.0.dev29}/src/fere_sdk/models.py +47 -0
- {fere_sdk-0.3.1.dev27 → fere_sdk-0.4.0.dev29}/.gitignore +0 -0
- {fere_sdk-0.3.1.dev27 → fere_sdk-0.4.0.dev29}/README.md +0 -0
- {fere_sdk-0.3.1.dev27 → fere_sdk-0.4.0.dev29}/src/fere_sdk/__init__.py +0 -0
- {fere_sdk-0.3.1.dev27 → fere_sdk-0.4.0.dev29}/src/fere_sdk/auth.py +0 -0
|
@@ -22,7 +22,9 @@ from .models import (
|
|
|
22
22
|
DepositRequest,
|
|
23
23
|
HooksRequest,
|
|
24
24
|
LimitOrderRequest,
|
|
25
|
+
SecurityCheckResponse,
|
|
25
26
|
SwapRequest,
|
|
27
|
+
TokenToCheck,
|
|
26
28
|
WithdrawRequest,
|
|
27
29
|
)
|
|
28
30
|
|
|
@@ -223,6 +225,29 @@ class FereClient:
|
|
|
223
225
|
)
|
|
224
226
|
return await self._api.set_hooks(req)
|
|
225
227
|
|
|
228
|
+
async def check_token_security(
|
|
229
|
+
self,
|
|
230
|
+
tokens: list[TokenToCheck] | list[dict],
|
|
231
|
+
) -> SecurityCheckResponse:
|
|
232
|
+
"""Pre-check tokens for honeypot / scam / rug-pull flags.
|
|
233
|
+
|
|
234
|
+
Pass a list of TokenToCheck or plain dicts with token_address
|
|
235
|
+
and chain_id. If a token is flagged and the user still wants
|
|
236
|
+
to proceed, call ``swap(..., bypass_security_check=True)``.
|
|
237
|
+
"""
|
|
238
|
+
normalized: list[TokenToCheck] = []
|
|
239
|
+
for t in tokens:
|
|
240
|
+
if isinstance(t, TokenToCheck):
|
|
241
|
+
normalized.append(t)
|
|
242
|
+
else:
|
|
243
|
+
normalized.append(
|
|
244
|
+
TokenToCheck(
|
|
245
|
+
token_address=t["token_address"],
|
|
246
|
+
chain_id=t["chain_id"],
|
|
247
|
+
)
|
|
248
|
+
)
|
|
249
|
+
return await self._api.check_token_security(normalized)
|
|
250
|
+
|
|
226
251
|
# ----------------------------------------------------------
|
|
227
252
|
# Earn (blocks until complete)
|
|
228
253
|
# ----------------------------------------------------------
|
|
@@ -16,10 +16,14 @@ from .models import (
|
|
|
16
16
|
DepositRequest,
|
|
17
17
|
HooksRequest,
|
|
18
18
|
LimitOrderRequest,
|
|
19
|
+
SecurityCheckResponse,
|
|
20
|
+
SecurityCheckSummary,
|
|
19
21
|
SwapRequest,
|
|
20
22
|
TaskResponse,
|
|
21
23
|
TaskStatusResponse,
|
|
22
24
|
TokenInfo,
|
|
25
|
+
TokenSecurityResult,
|
|
26
|
+
TokenToCheck,
|
|
23
27
|
WithdrawRequest,
|
|
24
28
|
)
|
|
25
29
|
|
|
@@ -305,6 +309,49 @@ class FereAPI:
|
|
|
305
309
|
"""POST /v1/hooks"""
|
|
306
310
|
return await self._authed_post("/v1/hooks", request.to_dict())
|
|
307
311
|
|
|
312
|
+
# ----------------------------------------------------------
|
|
313
|
+
# Security
|
|
314
|
+
# ----------------------------------------------------------
|
|
315
|
+
|
|
316
|
+
async def check_token_security(
|
|
317
|
+
self,
|
|
318
|
+
tokens: list[TokenToCheck],
|
|
319
|
+
) -> SecurityCheckResponse:
|
|
320
|
+
"""POST /v1/security/check.
|
|
321
|
+
|
|
322
|
+
Pre-check whether output tokens have been flagged by Honeypot.is
|
|
323
|
+
(EVM) or RugCheck.xyz (Solana) before submitting a swap. If a
|
|
324
|
+
token is flagged and the user still wants to proceed, pass
|
|
325
|
+
bypass_security_check=true on the swap request.
|
|
326
|
+
"""
|
|
327
|
+
data = await self._authed_post(
|
|
328
|
+
"/v1/security/check",
|
|
329
|
+
{"tokens": [t.to_dict() for t in tokens]},
|
|
330
|
+
)
|
|
331
|
+
results = [
|
|
332
|
+
TokenSecurityResult(
|
|
333
|
+
token_address=r["token_address"],
|
|
334
|
+
chain_id=r["chain_id"],
|
|
335
|
+
allowed=r["allowed"],
|
|
336
|
+
status=r["status"],
|
|
337
|
+
provider=r["provider"],
|
|
338
|
+
reason=r.get("reason"),
|
|
339
|
+
risk_details=r.get("risk_details"),
|
|
340
|
+
)
|
|
341
|
+
for r in data.get("results", [])
|
|
342
|
+
]
|
|
343
|
+
s = data.get("summary", {})
|
|
344
|
+
summary = SecurityCheckSummary(
|
|
345
|
+
total=s.get("total", 0),
|
|
346
|
+
passed=s.get("passed", 0),
|
|
347
|
+
failed=s.get("failed", 0),
|
|
348
|
+
warning=s.get("warning", 0),
|
|
349
|
+
api_unavailable=s.get("api_unavailable", 0),
|
|
350
|
+
unsupported_chain=s.get("unsupported_chain", 0),
|
|
351
|
+
skipped=s.get("skipped", 0),
|
|
352
|
+
)
|
|
353
|
+
return SecurityCheckResponse(results=results, summary=summary)
|
|
354
|
+
|
|
308
355
|
# ----------------------------------------------------------
|
|
309
356
|
# Wallets
|
|
310
357
|
# ----------------------------------------------------------
|
|
@@ -18,6 +18,10 @@ __all__ = [
|
|
|
18
18
|
"HooksRequest",
|
|
19
19
|
"DepositRequest",
|
|
20
20
|
"WithdrawRequest",
|
|
21
|
+
"TokenToCheck",
|
|
22
|
+
"TokenSecurityResult",
|
|
23
|
+
"SecurityCheckSummary",
|
|
24
|
+
"SecurityCheckResponse",
|
|
21
25
|
"TaskTimeoutError",
|
|
22
26
|
]
|
|
23
27
|
|
|
@@ -78,6 +82,7 @@ class SwapRequest:
|
|
|
78
82
|
stop_loss: dict | None = None
|
|
79
83
|
take_profit: dict | None = None
|
|
80
84
|
cancel_conditional_orders: bool | None = None
|
|
85
|
+
bypass_security_check: bool | None = None
|
|
81
86
|
|
|
82
87
|
def to_dict(self) -> dict:
|
|
83
88
|
d: dict = {
|
|
@@ -95,9 +100,51 @@ class SwapRequest:
|
|
|
95
100
|
d["take_profit"] = self.take_profit
|
|
96
101
|
if self.cancel_conditional_orders is not None:
|
|
97
102
|
d["cancel_conditional_orders"] = self.cancel_conditional_orders
|
|
103
|
+
if self.bypass_security_check is not None:
|
|
104
|
+
d["bypass_security_check"] = self.bypass_security_check
|
|
98
105
|
return d
|
|
99
106
|
|
|
100
107
|
|
|
108
|
+
@dataclass
|
|
109
|
+
class TokenToCheck:
|
|
110
|
+
token_address: str
|
|
111
|
+
chain_id: int | str
|
|
112
|
+
|
|
113
|
+
def to_dict(self) -> dict:
|
|
114
|
+
return {
|
|
115
|
+
"token_address": self.token_address,
|
|
116
|
+
"chain_id": self.chain_id,
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
@dataclass
|
|
121
|
+
class TokenSecurityResult:
|
|
122
|
+
token_address: str
|
|
123
|
+
chain_id: int
|
|
124
|
+
allowed: bool
|
|
125
|
+
status: str
|
|
126
|
+
provider: str
|
|
127
|
+
reason: str | None = None
|
|
128
|
+
risk_details: dict | None = None
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
@dataclass
|
|
132
|
+
class SecurityCheckSummary:
|
|
133
|
+
total: int
|
|
134
|
+
passed: int
|
|
135
|
+
failed: int
|
|
136
|
+
warning: int
|
|
137
|
+
api_unavailable: int
|
|
138
|
+
unsupported_chain: int = 0
|
|
139
|
+
skipped: int = 0
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
@dataclass
|
|
143
|
+
class SecurityCheckResponse:
|
|
144
|
+
results: list[TokenSecurityResult]
|
|
145
|
+
summary: SecurityCheckSummary
|
|
146
|
+
|
|
147
|
+
|
|
101
148
|
@dataclass
|
|
102
149
|
class LimitOrderRequest:
|
|
103
150
|
chain_id_in: int
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|