tensorfeed 1.28.0__tar.gz → 2.0.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.
- {tensorfeed-1.28.0 → tensorfeed-2.0.0}/PKG-INFO +1 -1
- {tensorfeed-1.28.0 → tensorfeed-2.0.0}/pyproject.toml +1 -1
- {tensorfeed-1.28.0 → tensorfeed-2.0.0}/tensorfeed/__init__.py +1 -1
- {tensorfeed-1.28.0 → tensorfeed-2.0.0}/tensorfeed/client.py +69 -14
- {tensorfeed-1.28.0 → tensorfeed-2.0.0}/tensorfeed/web3_signer.py +10 -3
- {tensorfeed-1.28.0 → tensorfeed-2.0.0}/tensorfeed.egg-info/PKG-INFO +1 -1
- {tensorfeed-1.28.0 → tensorfeed-2.0.0}/README.md +0 -0
- {tensorfeed-1.28.0 → tensorfeed-2.0.0}/setup.cfg +0 -0
- {tensorfeed-1.28.0 → tensorfeed-2.0.0}/tensorfeed/crewai.py +0 -0
- {tensorfeed-1.28.0 → tensorfeed-2.0.0}/tensorfeed/langchain.py +0 -0
- {tensorfeed-1.28.0 → tensorfeed-2.0.0}/tensorfeed/llamaindex.py +0 -0
- {tensorfeed-1.28.0 → tensorfeed-2.0.0}/tensorfeed.egg-info/SOURCES.txt +0 -0
- {tensorfeed-1.28.0 → tensorfeed-2.0.0}/tensorfeed.egg-info/dependency_links.txt +0 -0
- {tensorfeed-1.28.0 → tensorfeed-2.0.0}/tensorfeed.egg-info/requires.txt +0 -0
- {tensorfeed-1.28.0 → tensorfeed-2.0.0}/tensorfeed.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: tensorfeed
|
|
3
|
-
Version:
|
|
3
|
+
Version: 2.0.0
|
|
4
4
|
Summary: Python SDK for the TensorFeed.ai API: AI news, status, model pricing, premium routing + history series + webhook watches, agent payments via USDC on Base (optional web3 auto-send)
|
|
5
5
|
Author-email: "TensorFeed.ai" <feedback@tensorfeed.ai>
|
|
6
6
|
License-Expression: MIT
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "tensorfeed"
|
|
7
|
-
version = "
|
|
7
|
+
version = "2.0.0"
|
|
8
8
|
description = "Python SDK for the TensorFeed.ai API: AI news, status, model pricing, premium routing + history series + webhook watches, agent payments via USDC on Base (optional web3 auto-send)"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = "MIT"
|
|
@@ -565,26 +565,35 @@ class TensorFeed:
|
|
|
565
565
|
"""
|
|
566
566
|
return self._get("/payment/info")
|
|
567
567
|
|
|
568
|
-
def buy_credits(self, *, amount_usd: float) -> dict[str, Any]:
|
|
569
|
-
"""Generate a 30-min payment quote.
|
|
568
|
+
def buy_credits(self, *, amount_usd: float, sender_wallet: str) -> dict[str, Any]:
|
|
569
|
+
"""Generate a 30-min payment quote bound to a sender wallet.
|
|
570
570
|
|
|
571
571
|
Returns a dict with ``wallet``, ``memo``, ``amount_usd``, ``credits``,
|
|
572
|
-
``expires_at``, ``ttl_seconds``, ``next_step``.
|
|
572
|
+
``sender_wallet``, ``expires_at``, ``ttl_seconds``, ``next_step``.
|
|
573
573
|
|
|
574
|
-
Send the USDC on Base
|
|
575
|
-
|
|
574
|
+
Send the USDC on Base FROM ``sender_wallet`` TO ``wallet``, then
|
|
575
|
+
call ``confirm()`` with the tx hash and the returned ``memo`` as
|
|
576
|
+
nonce. The on-chain sender must match ``sender_wallet`` exactly
|
|
577
|
+
or ``confirm()`` will reject with ``sender_mismatch``. This is
|
|
578
|
+
the post-2026-05-05 binding that closes the public-mempool tx
|
|
579
|
+
sniper attack.
|
|
576
580
|
|
|
577
581
|
Args:
|
|
578
582
|
amount_usd: USD value of credits to buy. Must be 0.5 to 10000.
|
|
579
583
|
Volume discounts apply at $5 (10%), $30 (25%), $200 (40%).
|
|
584
|
+
sender_wallet: 0x-prefixed 40-char EVM address that will sign
|
|
585
|
+
the on-chain USDC transfer. Required.
|
|
580
586
|
"""
|
|
581
|
-
return self._post(
|
|
587
|
+
return self._post(
|
|
588
|
+
"/payment/buy-credits",
|
|
589
|
+
{"amount_usd": amount_usd, "sender_wallet": sender_wallet},
|
|
590
|
+
)
|
|
582
591
|
|
|
583
592
|
def confirm(
|
|
584
593
|
self,
|
|
585
594
|
*,
|
|
586
595
|
tx_hash: str,
|
|
587
|
-
nonce: str
|
|
596
|
+
nonce: str,
|
|
588
597
|
) -> dict[str, Any]:
|
|
589
598
|
"""Verify a USDC tx on-chain and mint a credit token.
|
|
590
599
|
|
|
@@ -597,14 +606,12 @@ class TensorFeed:
|
|
|
597
606
|
|
|
598
607
|
Args:
|
|
599
608
|
tx_hash: 0x-prefixed Base mainnet transaction hash
|
|
600
|
-
nonce:
|
|
601
|
-
the
|
|
602
|
-
|
|
603
|
-
|
|
609
|
+
nonce: memo from ``buy_credits()``. Required as of 2026-05-05;
|
|
610
|
+
the legacy no-nonce path is closed because it allowed
|
|
611
|
+
public-mempool observers to steal credits by racing the
|
|
612
|
+
rightful payer.
|
|
604
613
|
"""
|
|
605
|
-
body: dict[str, Any] = {"tx_hash": tx_hash}
|
|
606
|
-
if nonce is not None:
|
|
607
|
-
body["nonce"] = nonce
|
|
614
|
+
body: dict[str, Any] = {"tx_hash": tx_hash, "nonce": nonce}
|
|
608
615
|
result = self._post("/payment/confirm", body)
|
|
609
616
|
if isinstance(result, dict) and result.get("ok") and result.get("token"):
|
|
610
617
|
self.token = str(result["token"])
|
|
@@ -1026,6 +1033,54 @@ class TensorFeed:
|
|
|
1026
1033
|
fire_cap=fire_cap,
|
|
1027
1034
|
)
|
|
1028
1035
|
|
|
1036
|
+
def create_leaderboard_rank_watch(
|
|
1037
|
+
self,
|
|
1038
|
+
*,
|
|
1039
|
+
provider: str,
|
|
1040
|
+
op: str,
|
|
1041
|
+
threshold: int | None = None,
|
|
1042
|
+
callback_url: str,
|
|
1043
|
+
secret: str | None = None,
|
|
1044
|
+
fire_cap: int | None = None,
|
|
1045
|
+
) -> dict[str, Any]:
|
|
1046
|
+
"""Convenience helper for leaderboard rank-change webhook watches.
|
|
1047
|
+
|
|
1048
|
+
Costs 1 credit at registration. Fires when the provider's rank in
|
|
1049
|
+
the cross-provider 7-day uptime leaderboard crosses a threshold or
|
|
1050
|
+
changes. Useful for SRE / vendor-management workflows tracking
|
|
1051
|
+
which AI provider is currently most reliable relative to the field.
|
|
1052
|
+
|
|
1053
|
+
Rank semantics: rank 1 = best (highest uptime).
|
|
1054
|
+
|
|
1055
|
+
Args:
|
|
1056
|
+
provider: Provider name or slug (case-insensitive). e.g.
|
|
1057
|
+
'claude', 'OpenAI API', 'AWS Bedrock'.
|
|
1058
|
+
op: 'drops_below', 'rises_above', or 'changes'.
|
|
1059
|
+
threshold: Required for drops_below / rises_above; integer
|
|
1060
|
+
rank position (e.g. 5 means "below #5"). Ignored for
|
|
1061
|
+
'changes'.
|
|
1062
|
+
callback_url: HTTPS URL to POST to on each fire.
|
|
1063
|
+
secret: Optional HMAC shared secret.
|
|
1064
|
+
fire_cap: Max fires before auto-disable (default 100).
|
|
1065
|
+
|
|
1066
|
+
Returns:
|
|
1067
|
+
Same shape as ``create_watch``.
|
|
1068
|
+
|
|
1069
|
+
Raises:
|
|
1070
|
+
ValueError: if no token is set on the client
|
|
1071
|
+
PaymentRequired: if the token has insufficient credits
|
|
1072
|
+
TensorFeedError: 400 on invalid spec or callback URL
|
|
1073
|
+
"""
|
|
1074
|
+
spec: dict[str, Any] = {"type": "leaderboard_rank", "provider": provider, "op": op}
|
|
1075
|
+
if threshold is not None:
|
|
1076
|
+
spec["threshold"] = threshold
|
|
1077
|
+
return self.create_watch(
|
|
1078
|
+
spec=spec,
|
|
1079
|
+
callback_url=callback_url,
|
|
1080
|
+
secret=secret,
|
|
1081
|
+
fire_cap=fire_cap,
|
|
1082
|
+
)
|
|
1083
|
+
|
|
1029
1084
|
# ── Paid: provider deep-dive (Tier 1, 1 credit) ────────────────
|
|
1030
1085
|
|
|
1031
1086
|
def provider_deepdive(self, provider: str) -> dict[str, Any]:
|
|
@@ -106,8 +106,10 @@ def auto_purchase_credits(
|
|
|
106
106
|
account = Account.from_key(private_key)
|
|
107
107
|
sender = account.address
|
|
108
108
|
|
|
109
|
-
# Step 1: TensorFeed-side quote
|
|
110
|
-
|
|
109
|
+
# Step 1: TensorFeed-side quote, bound to this sender wallet so the
|
|
110
|
+
# post-2026-05-05 Tx-Sniper guard accepts the confirm. Must pass the
|
|
111
|
+
# exact lowercased address that will sign the on-chain transfer.
|
|
112
|
+
quote = tf.buy_credits(amount_usd=amount_usd, sender_wallet=sender.lower())
|
|
111
113
|
receiving_wallet = quote["wallet"]
|
|
112
114
|
memo = quote["memo"]
|
|
113
115
|
|
|
@@ -135,7 +137,12 @@ def auto_purchase_credits(
|
|
|
135
137
|
signed = Account.sign_transaction(tx, private_key=private_key)
|
|
136
138
|
raw_tx = getattr(signed, "raw_transaction", None) or getattr(signed, "rawTransaction")
|
|
137
139
|
tx_hash_bytes = w3.eth.send_raw_transaction(raw_tx)
|
|
138
|
-
|
|
140
|
+
# Older fix used `.lstrip("0x")` which silently corrupts hashes that
|
|
141
|
+
# contain leading zero bytes (rare but real, ~0.4% of txs). Modern
|
|
142
|
+
# web3.py returns HexBytes whose .hex() may or may not include the
|
|
143
|
+
# 0x prefix depending on version, so check and prepend explicitly.
|
|
144
|
+
raw_hex = tx_hash_bytes.hex()
|
|
145
|
+
tx_hash = raw_hex if raw_hex.startswith("0x") else "0x" + raw_hex
|
|
139
146
|
|
|
140
147
|
# Step 4: wait for confirmation
|
|
141
148
|
deadline = time.time() + wait_seconds
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: tensorfeed
|
|
3
|
-
Version:
|
|
3
|
+
Version: 2.0.0
|
|
4
4
|
Summary: Python SDK for the TensorFeed.ai API: AI news, status, model pricing, premium routing + history series + webhook watches, agent payments via USDC on Base (optional web3 auto-send)
|
|
5
5
|
Author-email: "TensorFeed.ai" <feedback@tensorfeed.ai>
|
|
6
6
|
License-Expression: MIT
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|