@blockrun/llm 2.12.0 → 3.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.
package/dist/index.cjs CHANGED
@@ -39,6 +39,7 @@ __export(index_exports, {
39
39
  KNOWN_PROVIDERS: () => KNOWN_PROVIDERS,
40
40
  LLMClient: () => LLMClient,
41
41
  MusicClient: () => MusicClient,
42
+ NETWORK_ALIASES: () => NETWORK_ALIASES,
42
43
  OpenAI: () => OpenAI,
43
44
  PHONE_PRICES: () => PHONE_PRICES,
44
45
  PORTRAIT_ENROLLMENT_PRICE_USD: () => PORTRAIT_ENROLLMENT_PRICE_USD,
@@ -46,8 +47,11 @@ __export(index_exports, {
46
47
  PhoneClient: () => PhoneClient,
47
48
  PortraitClient: () => PortraitClient,
48
49
  PriceClient: () => PriceClient,
50
+ RPC_PRICE_USD: () => RPC_PRICE_USD,
51
+ RpcClient: () => RpcClient,
49
52
  SOLANA_NETWORK: () => SOLANA_NETWORK,
50
53
  SOLANA_WALLET_FILE_PATH: () => SOLANA_WALLET_FILE,
54
+ SUPPORTED_NETWORKS: () => SUPPORTED_NETWORKS,
51
55
  SearchClient: () => SearchClient,
52
56
  SolanaLLMClient: () => SolanaLLMClient,
53
57
  SpeechClient: () => SpeechClient,
@@ -59,7 +63,6 @@ __export(index_exports, {
59
63
  VoiceClient: () => VoiceClient,
60
64
  WALLET_DIR_PATH: () => WALLET_DIR_PATH,
61
65
  WALLET_FILE_PATH: () => WALLET_FILE_PATH,
62
- XClient: () => XClient,
63
66
  clearCache: () => clearCache,
64
67
  createPaymentPayload: () => createPaymentPayload,
65
68
  createSolanaPaymentPayload: () => createSolanaPaymentPayload,
@@ -1616,205 +1619,6 @@ var LLMClient = class _LLMClient {
1616
1619
  }
1617
1620
  throw lastError || new Error("All RPCs failed");
1618
1621
  }
1619
- // ============================================================
1620
- // X/Twitter endpoints (powered by AttentionVC)
1621
- // ============================================================
1622
- /**
1623
- * Look up X/Twitter user profiles by username.
1624
- *
1625
- * Powered by AttentionVC. $0.002 per user (min $0.02, max $0.20).
1626
- *
1627
- * @param usernames - Single username or array of usernames (without @)
1628
- */
1629
- async xUserLookup(usernames) {
1630
- const names = Array.isArray(usernames) ? usernames : [usernames];
1631
- const data = await this.requestWithPaymentRaw("/v1/x/users/lookup", { usernames: names });
1632
- return data;
1633
- }
1634
- /**
1635
- * Get followers of an X/Twitter user.
1636
- *
1637
- * Powered by AttentionVC. $0.05 per page (~200 accounts).
1638
- *
1639
- * @param username - X/Twitter username (without @)
1640
- * @param cursor - Pagination cursor from previous response
1641
- */
1642
- async xFollowers(username, cursor) {
1643
- const body = { username };
1644
- if (cursor !== void 0) body.cursor = cursor;
1645
- const data = await this.requestWithPaymentRaw("/v1/x/users/followers", body);
1646
- return data;
1647
- }
1648
- /**
1649
- * Get accounts an X/Twitter user is following.
1650
- *
1651
- * Powered by AttentionVC. $0.05 per page (~200 accounts).
1652
- *
1653
- * @param username - X/Twitter username (without @)
1654
- * @param cursor - Pagination cursor from previous response
1655
- */
1656
- async xFollowings(username, cursor) {
1657
- const body = { username };
1658
- if (cursor !== void 0) body.cursor = cursor;
1659
- const data = await this.requestWithPaymentRaw("/v1/x/users/followings", body);
1660
- return data;
1661
- }
1662
- /**
1663
- * Get detailed profile info for a single X/Twitter user.
1664
- *
1665
- * Powered by AttentionVC. $0.002 per request.
1666
- *
1667
- * @param username - X/Twitter username (without @)
1668
- */
1669
- async xUserInfo(username) {
1670
- const data = await this.requestWithPaymentRaw("/v1/x/users/info", { username });
1671
- return data;
1672
- }
1673
- /**
1674
- * Get verified (blue-check) followers of an X/Twitter user.
1675
- *
1676
- * Powered by AttentionVC. $0.048 per page.
1677
- *
1678
- * @param userId - X/Twitter user ID (not username)
1679
- * @param cursor - Pagination cursor from previous response
1680
- */
1681
- async xVerifiedFollowers(userId, cursor) {
1682
- const body = { userId };
1683
- if (cursor !== void 0) body.cursor = cursor;
1684
- const data = await this.requestWithPaymentRaw("/v1/x/users/verified-followers", body);
1685
- return data;
1686
- }
1687
- /**
1688
- * Get tweets posted by an X/Twitter user.
1689
- *
1690
- * Powered by AttentionVC. $0.032 per page.
1691
- *
1692
- * @param username - X/Twitter username (without @)
1693
- * @param includeReplies - Include reply tweets (default: false)
1694
- * @param cursor - Pagination cursor from previous response
1695
- */
1696
- async xUserTweets(username, includeReplies = false, cursor) {
1697
- const body = { username, includeReplies };
1698
- if (cursor !== void 0) body.cursor = cursor;
1699
- const data = await this.requestWithPaymentRaw("/v1/x/users/tweets", body);
1700
- return data;
1701
- }
1702
- /**
1703
- * Get tweets that mention an X/Twitter user.
1704
- *
1705
- * Powered by AttentionVC. $0.032 per page.
1706
- *
1707
- * @param username - X/Twitter username (without @)
1708
- * @param sinceTime - Start time filter (ISO8601 or Unix timestamp)
1709
- * @param untilTime - End time filter (ISO8601 or Unix timestamp)
1710
- * @param cursor - Pagination cursor from previous response
1711
- */
1712
- async xUserMentions(username, sinceTime, untilTime, cursor) {
1713
- const body = { username };
1714
- if (sinceTime !== void 0) body.sinceTime = sinceTime;
1715
- if (untilTime !== void 0) body.untilTime = untilTime;
1716
- if (cursor !== void 0) body.cursor = cursor;
1717
- const data = await this.requestWithPaymentRaw("/v1/x/users/mentions", body);
1718
- return data;
1719
- }
1720
- /**
1721
- * Fetch full tweet data for up to 200 tweet IDs.
1722
- *
1723
- * Powered by AttentionVC. $0.16 per batch.
1724
- *
1725
- * @param tweetIds - Single tweet ID or array of tweet IDs (max 200)
1726
- */
1727
- async xTweetLookup(tweetIds) {
1728
- const ids = Array.isArray(tweetIds) ? tweetIds : [tweetIds];
1729
- const data = await this.requestWithPaymentRaw("/v1/x/tweets/lookup", { tweet_ids: ids });
1730
- return data;
1731
- }
1732
- /**
1733
- * Get replies to a specific tweet.
1734
- *
1735
- * Powered by AttentionVC. $0.032 per page.
1736
- *
1737
- * @param tweetId - The tweet ID to get replies for
1738
- * @param queryType - Sort order: 'Latest' or 'Default'
1739
- * @param cursor - Pagination cursor from previous response
1740
- */
1741
- async xTweetReplies(tweetId, queryType = "Latest", cursor) {
1742
- const body = { tweetId, queryType };
1743
- if (cursor !== void 0) body.cursor = cursor;
1744
- const data = await this.requestWithPaymentRaw("/v1/x/tweets/replies", body);
1745
- return data;
1746
- }
1747
- /**
1748
- * Get the full thread context for a tweet.
1749
- *
1750
- * Powered by AttentionVC. $0.032 per page.
1751
- *
1752
- * @param tweetId - The tweet ID to get thread for
1753
- * @param cursor - Pagination cursor from previous response
1754
- */
1755
- async xTweetThread(tweetId, cursor) {
1756
- const body = { tweetId };
1757
- if (cursor !== void 0) body.cursor = cursor;
1758
- const data = await this.requestWithPaymentRaw("/v1/x/tweets/thread", body);
1759
- return data;
1760
- }
1761
- /**
1762
- * Search X/Twitter with advanced query operators.
1763
- *
1764
- * Powered by AttentionVC. $0.032 per page.
1765
- *
1766
- * @param query - Search query (supports Twitter search operators)
1767
- * @param queryType - Sort order: 'Latest', 'Top', or 'Default'
1768
- * @param cursor - Pagination cursor from previous response
1769
- */
1770
- async xSearch(query, queryType = "Latest", cursor) {
1771
- const body = { query, queryType };
1772
- if (cursor !== void 0) body.cursor = cursor;
1773
- const data = await this.requestWithPaymentRaw("/v1/x/search", body);
1774
- return data;
1775
- }
1776
- /**
1777
- * Get current trending topics on X/Twitter.
1778
- *
1779
- * Powered by AttentionVC. $0.002 per request.
1780
- */
1781
- async xTrending() {
1782
- const data = await this.requestWithPaymentRaw("/v1/x/trending", {});
1783
- return data;
1784
- }
1785
- /**
1786
- * Get rising/viral articles from X/Twitter.
1787
- *
1788
- * Powered by AttentionVC intelligence layer. $0.05 per request.
1789
- */
1790
- async xArticlesRising() {
1791
- const data = await this.requestWithPaymentRaw("/v1/x/articles/rising", {});
1792
- return data;
1793
- }
1794
- /**
1795
- * Get author analytics and intelligence metrics for an X/Twitter user.
1796
- *
1797
- * Powered by AttentionVC intelligence layer. $0.02 per request.
1798
- *
1799
- * @param handle - X/Twitter handle (without @)
1800
- */
1801
- async xAuthorAnalytics(handle) {
1802
- const data = await this.requestWithPaymentRaw("/v1/x/authors", { handle });
1803
- return data;
1804
- }
1805
- /**
1806
- * Compare two X/Twitter authors side-by-side with intelligence metrics.
1807
- *
1808
- * Powered by AttentionVC intelligence layer. $0.05 per request.
1809
- *
1810
- * @param handle1 - First X/Twitter handle (without @)
1811
- * @param handle2 - Second X/Twitter handle (without @)
1812
- */
1813
- async xCompareAuthors(handle1, handle2) {
1814
- const data = await this.requestWithPaymentRaw("/v1/x/compare", { handle1, handle2 });
1815
- return data;
1816
- }
1817
- // ── Prediction Markets (Powered by Predexon) ────────────────────────────
1818
1622
  /**
1819
1623
  * Query Predexon prediction market data (GET endpoints).
1820
1624
  *
@@ -2650,11 +2454,33 @@ var VideoClient = class {
2650
2454
  "realFaceAssetId must be a Token360 asset id matching 'ta_[A-Za-z0-9]+' (e.g. 'ta_abc123xyz')"
2651
2455
  );
2652
2456
  }
2457
+ if (options?.lastFrameUrl && !options?.imageUrl) {
2458
+ throw new Error(
2459
+ "lastFrameUrl requires imageUrl: imageUrl seeds the FIRST frame and lastFrameUrl the FINAL frame \u2014 send both."
2460
+ );
2461
+ }
2462
+ if (options?.lastFrameUrl && options?.realFaceAssetId) {
2463
+ throw new Error(
2464
+ "lastFrameUrl and realFaceAssetId are mutually exclusive; first-and-last-frame uses imageUrl + lastFrameUrl."
2465
+ );
2466
+ }
2467
+ if (options?.referenceImageUrls?.length) {
2468
+ if (options.imageUrl || options.lastFrameUrl || options.realFaceAssetId) {
2469
+ throw new Error(
2470
+ "referenceImageUrls is mutually exclusive with imageUrl, lastFrameUrl, and realFaceAssetId."
2471
+ );
2472
+ }
2473
+ if (options.referenceImageUrls.length > 9) {
2474
+ throw new Error("referenceImageUrls accepts at most 9 images.");
2475
+ }
2476
+ }
2653
2477
  const body = {
2654
2478
  model: options?.model || DEFAULT_MODEL4,
2655
2479
  prompt
2656
2480
  };
2657
2481
  if (options?.imageUrl) body.image_url = options.imageUrl;
2482
+ if (options?.lastFrameUrl) body.last_frame_url = options.lastFrameUrl;
2483
+ if (options?.referenceImageUrls?.length) body.reference_image_urls = options.referenceImageUrls;
2658
2484
  if (options?.realFaceAssetId) body.real_face_asset_id = options.realFaceAssetId;
2659
2485
  if (options?.durationSeconds !== void 0) body.duration_seconds = options.durationSeconds;
2660
2486
  if (options?.aspectRatio) body.aspect_ratio = options.aspectRatio;
@@ -3518,217 +3344,10 @@ var SearchClient = class {
3518
3344
  }
3519
3345
  };
3520
3346
 
3521
- // src/x-client.ts
3347
+ // src/price.ts
3522
3348
  var import_accounts11 = require("viem/accounts");
3523
3349
  var DEFAULT_API_URL10 = "https://blockrun.ai/api";
3524
- var DEFAULT_TIMEOUT10 = 6e4;
3525
- var XClient = class _XClient {
3526
- account;
3527
- privateKey;
3528
- apiUrl;
3529
- timeout;
3530
- static deprecationWarned = false;
3531
- constructor(options = {}) {
3532
- if (!_XClient.deprecationWarned) {
3533
- console.warn(
3534
- "[@blockrun/llm] XClient: BlockRun's /v1/x/* (AttentionVC) integration was removed 2026-04-30. All calls will return HTTP 404 until a replacement X data upstream is reintroduced."
3535
- );
3536
- _XClient.deprecationWarned = true;
3537
- }
3538
- const envKey = typeof process !== "undefined" && process.env ? process.env.BLOCKRUN_WALLET_KEY || process.env.BASE_CHAIN_WALLET_KEY : void 0;
3539
- const privateKey = options.privateKey || envKey;
3540
- if (!privateKey) {
3541
- throw new Error(
3542
- "Private key required. Pass privateKey in options or set BLOCKRUN_WALLET_KEY environment variable."
3543
- );
3544
- }
3545
- validatePrivateKey(privateKey);
3546
- this.privateKey = privateKey;
3547
- this.account = (0, import_accounts11.privateKeyToAccount)(privateKey);
3548
- const apiUrl = options.apiUrl || DEFAULT_API_URL10;
3549
- validateApiUrl(apiUrl);
3550
- this.apiUrl = apiUrl.replace(/\/$/, "");
3551
- this.timeout = options.timeout || DEFAULT_TIMEOUT10;
3552
- }
3553
- // ───────── User endpoints ─────────
3554
- userLookup(usernames) {
3555
- return this.post("/v1/x/users/lookup", { usernames });
3556
- }
3557
- userInfo(username) {
3558
- return this.post("/v1/x/users/info", { username });
3559
- }
3560
- followers(username, cursor) {
3561
- const body = { username };
3562
- if (cursor) body.cursor = cursor;
3563
- return this.post("/v1/x/users/followers", body);
3564
- }
3565
- /** `/v1/x/users/following` (singular path variant). */
3566
- following(username, cursor) {
3567
- const body = { username };
3568
- if (cursor) body.cursor = cursor;
3569
- return this.post("/v1/x/users/following", body);
3570
- }
3571
- /** `/v1/x/users/followings` (plural path variant). */
3572
- followings(username, cursor) {
3573
- const body = { username };
3574
- if (cursor) body.cursor = cursor;
3575
- return this.post("/v1/x/users/followings", body);
3576
- }
3577
- verifiedFollowers(userId, cursor) {
3578
- const body = { userId };
3579
- if (cursor) body.cursor = cursor;
3580
- return this.post(
3581
- "/v1/x/users/verified-followers",
3582
- body
3583
- );
3584
- }
3585
- userTweets(options) {
3586
- if (!options.username && !options.userId) {
3587
- throw new Error("Either username or userId is required");
3588
- }
3589
- const body = {};
3590
- if (options.username) body.username = options.username;
3591
- if (options.userId) body.userId = options.userId;
3592
- if (options.cursor) body.cursor = options.cursor;
3593
- if (options.includeReplies !== void 0) body.includeReplies = options.includeReplies;
3594
- return this.post("/v1/x/users/tweets", body);
3595
- }
3596
- mentions(username, options) {
3597
- const body = { username };
3598
- if (options?.sinceTime) body.sinceTime = options.sinceTime;
3599
- if (options?.untilTime) body.untilTime = options.untilTime;
3600
- if (options?.cursor) body.cursor = options.cursor;
3601
- return this.post("/v1/x/users/mentions", body);
3602
- }
3603
- // ───────── Tweet endpoints ─────────
3604
- tweetLookup(tweetIds) {
3605
- return this.post("/v1/x/tweets/lookup", {
3606
- tweet_ids: tweetIds
3607
- });
3608
- }
3609
- tweetReplies(tweetId, options) {
3610
- const body = { tweetId };
3611
- if (options?.cursor) body.cursor = options.cursor;
3612
- if (options?.queryType) body.queryType = options.queryType;
3613
- return this.post("/v1/x/tweets/replies", body);
3614
- }
3615
- tweetThread(tweetId, cursor) {
3616
- const body = { tweetId };
3617
- if (cursor) body.cursor = cursor;
3618
- return this.post("/v1/x/tweets/thread", body);
3619
- }
3620
- // ───────── Search & discovery ─────────
3621
- search(query, options) {
3622
- const body = { query };
3623
- if (options?.queryType) body.queryType = options.queryType;
3624
- if (options?.cursor) body.cursor = options.cursor;
3625
- return this.post("/v1/x/search", body);
3626
- }
3627
- trending() {
3628
- return this.post("/v1/x/trending", {});
3629
- }
3630
- articlesRising() {
3631
- return this.post("/v1/x/articles/rising", {});
3632
- }
3633
- // ───────── Internals ─────────
3634
- async post(endpoint, body) {
3635
- const url = `${this.apiUrl}${endpoint}`;
3636
- const response = await this.fetchWithTimeout(url, {
3637
- method: "POST",
3638
- headers: { "Content-Type": "application/json" },
3639
- body: JSON.stringify(body)
3640
- });
3641
- if (response.status === 402) {
3642
- return this.payAndRetry(url, body, response);
3643
- }
3644
- if (!response.ok) {
3645
- let errorBody;
3646
- try {
3647
- errorBody = await response.json();
3648
- } catch {
3649
- errorBody = { error: "Request failed" };
3650
- }
3651
- throw new APIError(
3652
- `API error: ${response.status}`,
3653
- response.status,
3654
- sanitizeErrorResponse(errorBody)
3655
- );
3656
- }
3657
- return response.json();
3658
- }
3659
- async payAndRetry(url, body, response) {
3660
- let paymentHeader = response.headers.get("payment-required");
3661
- if (!paymentHeader) {
3662
- try {
3663
- const respBody = await response.json();
3664
- if (respBody.x402 || respBody.accepts) {
3665
- paymentHeader = btoa(JSON.stringify(respBody));
3666
- }
3667
- } catch {
3668
- }
3669
- }
3670
- if (!paymentHeader) {
3671
- throw new PaymentError("402 response but no payment requirements found");
3672
- }
3673
- const paymentRequired = parsePaymentRequired(paymentHeader);
3674
- const details = extractPaymentDetails(paymentRequired);
3675
- const paymentPayload = await createPaymentPayload(
3676
- this.privateKey,
3677
- this.account.address,
3678
- details.recipient,
3679
- details.amount,
3680
- details.network || "eip155:8453",
3681
- {
3682
- resourceUrl: details.resource?.url || url,
3683
- resourceDescription: details.resource?.description || "BlockRun X API",
3684
- maxTimeoutSeconds: details.maxTimeoutSeconds || 300,
3685
- extra: details.extra
3686
- }
3687
- );
3688
- const retry = await this.fetchWithTimeout(url, {
3689
- method: "POST",
3690
- headers: {
3691
- "Content-Type": "application/json",
3692
- "PAYMENT-SIGNATURE": paymentPayload
3693
- },
3694
- body: JSON.stringify(body)
3695
- });
3696
- if (retry.status === 402) {
3697
- throw new PaymentError("Payment was rejected. Check your wallet balance.");
3698
- }
3699
- if (!retry.ok) {
3700
- let errorBody;
3701
- try {
3702
- errorBody = await retry.json();
3703
- } catch {
3704
- errorBody = { error: "Request failed" };
3705
- }
3706
- throw new APIError(
3707
- `API error after payment: ${retry.status}`,
3708
- retry.status,
3709
- sanitizeErrorResponse(errorBody)
3710
- );
3711
- }
3712
- return retry.json();
3713
- }
3714
- async fetchWithTimeout(url, init) {
3715
- const controller = new AbortController();
3716
- const timeoutId = setTimeout(() => controller.abort(), this.timeout);
3717
- try {
3718
- return await fetch(url, { ...init, signal: controller.signal });
3719
- } finally {
3720
- clearTimeout(timeoutId);
3721
- }
3722
- }
3723
- getWalletAddress() {
3724
- return this.account.address;
3725
- }
3726
- };
3727
-
3728
- // src/price.ts
3729
- var import_accounts12 = require("viem/accounts");
3730
- var DEFAULT_API_URL11 = "https://blockrun.ai/api";
3731
- var DEFAULT_TIMEOUT11 = 3e4;
3350
+ var DEFAULT_TIMEOUT10 = 3e4;
3732
3351
  var PriceClient = class {
3733
3352
  account = null;
3734
3353
  privateKey = null;
@@ -3746,12 +3365,12 @@ var PriceClient = class {
3746
3365
  if (privateKey) {
3747
3366
  validatePrivateKey(privateKey);
3748
3367
  this.privateKey = privateKey;
3749
- this.account = (0, import_accounts12.privateKeyToAccount)(privateKey);
3368
+ this.account = (0, import_accounts11.privateKeyToAccount)(privateKey);
3750
3369
  }
3751
- const apiUrl = options.apiUrl || DEFAULT_API_URL11;
3370
+ const apiUrl = options.apiUrl || DEFAULT_API_URL10;
3752
3371
  validateApiUrl(apiUrl);
3753
3372
  this.apiUrl = apiUrl.replace(/\/$/, "");
3754
- this.timeout = options.timeout || DEFAULT_TIMEOUT11;
3373
+ this.timeout = options.timeout || DEFAULT_TIMEOUT10;
3755
3374
  }
3756
3375
  async price(category, symbol, options) {
3757
3376
  if (!symbol) throw new Error("symbol is required");
@@ -3930,9 +3549,9 @@ function buildUrl(base, query) {
3930
3549
  }
3931
3550
 
3932
3551
  // src/surf.ts
3933
- var import_accounts13 = require("viem/accounts");
3934
- var DEFAULT_API_URL12 = "https://blockrun.ai/api";
3935
- var DEFAULT_TIMEOUT12 = 6e4;
3552
+ var import_accounts12 = require("viem/accounts");
3553
+ var DEFAULT_API_URL11 = "https://blockrun.ai/api";
3554
+ var DEFAULT_TIMEOUT11 = 6e4;
3936
3555
  var SURF_PREFIX = "/v1/surf";
3937
3556
  var SurfClient = class {
3938
3557
  account;
@@ -3949,11 +3568,11 @@ var SurfClient = class {
3949
3568
  }
3950
3569
  validatePrivateKey(privateKey);
3951
3570
  this.privateKey = privateKey;
3952
- this.account = (0, import_accounts13.privateKeyToAccount)(privateKey);
3953
- const apiUrl = options.apiUrl || DEFAULT_API_URL12;
3571
+ this.account = (0, import_accounts12.privateKeyToAccount)(privateKey);
3572
+ const apiUrl = options.apiUrl || DEFAULT_API_URL11;
3954
3573
  validateApiUrl(apiUrl);
3955
3574
  this.apiUrl = apiUrl.replace(/\/$/, "");
3956
- this.timeout = options.timeout || DEFAULT_TIMEOUT12;
3575
+ this.timeout = options.timeout || DEFAULT_TIMEOUT11;
3957
3576
  }
3958
3577
  /**
3959
3578
  * GET a Surf endpoint. `path` is everything after `/v1/surf` (a leading
@@ -4084,6 +3703,259 @@ var SurfClient = class {
4084
3703
  }
4085
3704
  };
4086
3705
 
3706
+ // src/rpc.ts
3707
+ var import_accounts13 = require("viem/accounts");
3708
+ var DEFAULT_API_URL12 = "https://blockrun.ai/api";
3709
+ var DEFAULT_TIMEOUT12 = 6e4;
3710
+ var RPC_PRICE_USD = 2e-3;
3711
+ var SUPPORTED_NETWORKS = [
3712
+ // EVM
3713
+ "ethereum",
3714
+ "base",
3715
+ "arbitrum",
3716
+ "arbitrum-nova",
3717
+ "optimism",
3718
+ "polygon",
3719
+ "bsc",
3720
+ "avalanche",
3721
+ "fantom",
3722
+ "cronos",
3723
+ "celo",
3724
+ "gnosis",
3725
+ "zksync",
3726
+ "berachain",
3727
+ "unichain",
3728
+ "monad",
3729
+ "chiliz",
3730
+ "moonbeam",
3731
+ "aurora",
3732
+ "flare",
3733
+ "oasis",
3734
+ "kaia",
3735
+ "sonic",
3736
+ "xdc",
3737
+ "abstract",
3738
+ "hyperevm",
3739
+ "plume",
3740
+ "ronin",
3741
+ "rootstock",
3742
+ // Non-EVM (JSON-RPC-compatible)
3743
+ "solana",
3744
+ "bitcoin",
3745
+ "litecoin",
3746
+ "dogecoin",
3747
+ "bitcoin-cash",
3748
+ "near",
3749
+ "sui",
3750
+ "ripple",
3751
+ "polkadot",
3752
+ "kusama",
3753
+ "zcash"
3754
+ ];
3755
+ var NETWORK_ALIASES = {
3756
+ eth: "ethereum",
3757
+ arb: "arbitrum",
3758
+ "arbitrum-one": "arbitrum",
3759
+ "arb-one": "arbitrum",
3760
+ "arb-nova": "arbitrum-nova",
3761
+ op: "optimism",
3762
+ matic: "polygon",
3763
+ pol: "polygon",
3764
+ bnb: "bsc",
3765
+ binance: "bsc",
3766
+ "binance-smart-chain": "bsc",
3767
+ avax: "avalanche",
3768
+ ftm: "fantom",
3769
+ bera: "berachain",
3770
+ klaytn: "kaia",
3771
+ chz: "chiliz",
3772
+ hyperliquid: "hyperevm",
3773
+ rsk: "rootstock",
3774
+ sol: "solana",
3775
+ btc: "bitcoin",
3776
+ ltc: "litecoin",
3777
+ doge: "dogecoin",
3778
+ bch: "bitcoin-cash",
3779
+ xrp: "ripple",
3780
+ xrpl: "ripple",
3781
+ dot: "polkadot",
3782
+ zec: "zcash"
3783
+ };
3784
+ var RpcClient = class {
3785
+ account;
3786
+ privateKey;
3787
+ apiUrl;
3788
+ timeout;
3789
+ sessionTotalUsd = 0;
3790
+ sessionCalls = 0;
3791
+ constructor(options = {}) {
3792
+ const envKey = typeof process !== "undefined" && process.env ? process.env.BLOCKRUN_WALLET_KEY || process.env.BASE_CHAIN_WALLET_KEY : void 0;
3793
+ const privateKey = options.privateKey || envKey;
3794
+ if (!privateKey) {
3795
+ throw new Error(
3796
+ "Private key required. Pass privateKey in options or set BLOCKRUN_WALLET_KEY environment variable."
3797
+ );
3798
+ }
3799
+ validatePrivateKey(privateKey);
3800
+ this.privateKey = privateKey;
3801
+ this.account = (0, import_accounts13.privateKeyToAccount)(privateKey);
3802
+ const apiUrl = options.apiUrl || DEFAULT_API_URL12;
3803
+ validateApiUrl(apiUrl);
3804
+ this.apiUrl = apiUrl.replace(/\/$/, "");
3805
+ this.timeout = options.timeout || DEFAULT_TIMEOUT12;
3806
+ }
3807
+ /**
3808
+ * Make a single JSON-RPC 2.0 call. Flat $0.002.
3809
+ *
3810
+ * @param network - Chain name (e.g. "ethereum", "base", "solana") or a
3811
+ * common alias ("eth", "sol", "matic", ...). See
3812
+ * SUPPORTED_NETWORKS / NETWORK_ALIASES.
3813
+ * @param method - Chain RPC method, e.g. "eth_blockNumber", "eth_call",
3814
+ * "eth_getBalance" (EVM) or "getSlot", "getAccountInfo"
3815
+ * (Solana).
3816
+ * @param params - Method-specific params array (optional).
3817
+ * @returns RpcResponse with `result` (or JSON-RPC `error`), plus
3818
+ * `network`, `cacheHit` and `txHash` metadata.
3819
+ *
3820
+ * @example
3821
+ * const block = await client.call('ethereum', 'eth_blockNumber');
3822
+ * console.log(parseInt(block.result as string, 16));
3823
+ */
3824
+ async call(network, method, params) {
3825
+ const body = { jsonrpc: "2.0", id: 1, method };
3826
+ if (params !== void 0) body.params = params;
3827
+ const { data, headers } = await this.requestWithPayment(network, body);
3828
+ return this.toResponse(data, headers);
3829
+ }
3830
+ /**
3831
+ * Make a JSON-RPC 2.0 batch call. Priced per element ($0.002 x N).
3832
+ *
3833
+ * @param network - Chain name or alias (see {@link call}).
3834
+ * @param requests - Requests, each with a `method` and optional
3835
+ * `params` / `id`. `jsonrpc` and missing ids are
3836
+ * filled in automatically.
3837
+ * @returns Array of RpcResponse, in upstream order.
3838
+ *
3839
+ * @example
3840
+ * const out = await client.batch('base', [
3841
+ * { method: 'eth_blockNumber' },
3842
+ * { method: 'eth_gasPrice' },
3843
+ * ]);
3844
+ */
3845
+ async batch(network, requests) {
3846
+ if (!requests.length) {
3847
+ throw new Error("batch requires at least one request");
3848
+ }
3849
+ const body = requests.map((req, i) => {
3850
+ if (!req.method) throw new Error(`batch request ${i} is missing 'method'`);
3851
+ return { jsonrpc: "2.0", id: i + 1, ...req };
3852
+ });
3853
+ const { data, headers } = await this.requestWithPayment(network, body);
3854
+ const items = Array.isArray(data) ? data : [data];
3855
+ return items.map((item) => this.toResponse(item, headers));
3856
+ }
3857
+ toResponse(data, headers) {
3858
+ const base = data !== null && typeof data === "object" && !Array.isArray(data) ? { ...data } : { result: data };
3859
+ const network = headers.get("x-network");
3860
+ if (network) base.network = network;
3861
+ base.cacheHit = (headers.get("x-cache") || "").toUpperCase() === "HIT";
3862
+ const txHash = headers.get("x-payment-receipt") || headers.get("X-Payment-Receipt");
3863
+ if (txHash) base.txHash = txHash;
3864
+ return base;
3865
+ }
3866
+ async requestWithPayment(network, body) {
3867
+ const endpoint = `/v1/rpc/${network}`;
3868
+ const url = `${this.apiUrl}${endpoint}`;
3869
+ const response = await this.fetchWithTimeout(url, {
3870
+ method: "POST",
3871
+ headers: { "Content-Type": "application/json" },
3872
+ body: JSON.stringify(body)
3873
+ });
3874
+ if (response.status === 402) {
3875
+ return this.handlePaymentAndRetry(url, endpoint, body, response);
3876
+ }
3877
+ if (!response.ok) {
3878
+ let errorBody;
3879
+ try {
3880
+ errorBody = await response.json();
3881
+ } catch {
3882
+ errorBody = { error: "Request failed" };
3883
+ }
3884
+ throw new APIError(`API error: ${response.status}`, response.status, sanitizeErrorResponse(errorBody));
3885
+ }
3886
+ return { data: await response.json(), headers: response.headers };
3887
+ }
3888
+ async handlePaymentAndRetry(url, endpoint, body, response) {
3889
+ let paymentHeader = response.headers.get("payment-required");
3890
+ if (!paymentHeader) {
3891
+ try {
3892
+ const respBody = await response.json();
3893
+ if (respBody.x402 || respBody.accepts) {
3894
+ paymentHeader = btoa(JSON.stringify(respBody));
3895
+ }
3896
+ } catch {
3897
+ }
3898
+ }
3899
+ if (!paymentHeader) {
3900
+ throw new PaymentError("402 response but no payment requirements found");
3901
+ }
3902
+ const paymentRequired = parsePaymentRequired(paymentHeader);
3903
+ const details = extractPaymentDetails(paymentRequired);
3904
+ const paymentPayload = await createPaymentPayload(
3905
+ this.privateKey,
3906
+ this.account.address,
3907
+ details.recipient,
3908
+ details.amount,
3909
+ details.network || "eip155:8453",
3910
+ {
3911
+ resourceUrl: details.resource?.url || `${this.apiUrl}${endpoint}`,
3912
+ resourceDescription: details.resource?.description || "BlockRun Multi-chain RPC",
3913
+ maxTimeoutSeconds: details.maxTimeoutSeconds || 300,
3914
+ extra: details.extra
3915
+ }
3916
+ );
3917
+ const retryResponse = await this.fetchWithTimeout(url, {
3918
+ method: "POST",
3919
+ headers: {
3920
+ "Content-Type": "application/json",
3921
+ "PAYMENT-SIGNATURE": paymentPayload
3922
+ },
3923
+ body: JSON.stringify(body)
3924
+ });
3925
+ if (retryResponse.status === 402) {
3926
+ throw new PaymentError("Payment was rejected. Check your wallet balance.");
3927
+ }
3928
+ if (!retryResponse.ok) {
3929
+ let errorBody;
3930
+ try {
3931
+ errorBody = await retryResponse.json();
3932
+ } catch {
3933
+ errorBody = { error: "Request failed" };
3934
+ }
3935
+ throw new APIError(`API error after payment: ${retryResponse.status}`, retryResponse.status, sanitizeErrorResponse(errorBody));
3936
+ }
3937
+ this.sessionCalls++;
3938
+ const paidUsd = Number(details.amount) / 1e6;
3939
+ if (Number.isFinite(paidUsd)) this.sessionTotalUsd += paidUsd;
3940
+ return { data: await retryResponse.json(), headers: retryResponse.headers };
3941
+ }
3942
+ async fetchWithTimeout(url, options) {
3943
+ const controller = new AbortController();
3944
+ const timeoutId = setTimeout(() => controller.abort(), this.timeout);
3945
+ try {
3946
+ return await fetch(url, { ...options, signal: controller.signal });
3947
+ } finally {
3948
+ clearTimeout(timeoutId);
3949
+ }
3950
+ }
3951
+ getWalletAddress() {
3952
+ return this.account.address;
3953
+ }
3954
+ getSpending() {
3955
+ return { totalUsd: this.sessionTotalUsd, calls: this.sessionCalls };
3956
+ }
3957
+ };
3958
+
4087
3959
  // src/blockrun.ts
4088
3960
  var import_accounts14 = require("viem/accounts");
4089
3961
  var DEFAULT_API_URL13 = "https://blockrun.ai/api";
@@ -4878,89 +4750,6 @@ var SolanaLLMClient = class {
4878
4750
  const data = await this.requestWithPaymentRaw("/v1/search", body);
4879
4751
  return data;
4880
4752
  }
4881
- // ============================================================
4882
- // X/Twitter endpoints (powered by AttentionVC)
4883
- // ============================================================
4884
- async xUserLookup(usernames) {
4885
- const names = Array.isArray(usernames) ? usernames : [usernames];
4886
- const data = await this.requestWithPaymentRaw("/v1/x/users/lookup", { usernames: names });
4887
- return data;
4888
- }
4889
- async xFollowers(username, cursor) {
4890
- const body = { username };
4891
- if (cursor !== void 0) body.cursor = cursor;
4892
- const data = await this.requestWithPaymentRaw("/v1/x/users/followers", body);
4893
- return data;
4894
- }
4895
- async xFollowings(username, cursor) {
4896
- const body = { username };
4897
- if (cursor !== void 0) body.cursor = cursor;
4898
- const data = await this.requestWithPaymentRaw("/v1/x/users/followings", body);
4899
- return data;
4900
- }
4901
- async xUserInfo(username) {
4902
- const data = await this.requestWithPaymentRaw("/v1/x/users/info", { username });
4903
- return data;
4904
- }
4905
- async xVerifiedFollowers(userId, cursor) {
4906
- const body = { userId };
4907
- if (cursor !== void 0) body.cursor = cursor;
4908
- const data = await this.requestWithPaymentRaw("/v1/x/users/verified-followers", body);
4909
- return data;
4910
- }
4911
- async xUserTweets(username, includeReplies = false, cursor) {
4912
- const body = { username, includeReplies };
4913
- if (cursor !== void 0) body.cursor = cursor;
4914
- const data = await this.requestWithPaymentRaw("/v1/x/users/tweets", body);
4915
- return data;
4916
- }
4917
- async xUserMentions(username, sinceTime, untilTime, cursor) {
4918
- const body = { username };
4919
- if (sinceTime !== void 0) body.sinceTime = sinceTime;
4920
- if (untilTime !== void 0) body.untilTime = untilTime;
4921
- if (cursor !== void 0) body.cursor = cursor;
4922
- const data = await this.requestWithPaymentRaw("/v1/x/users/mentions", body);
4923
- return data;
4924
- }
4925
- async xTweetLookup(tweetIds) {
4926
- const ids = Array.isArray(tweetIds) ? tweetIds : [tweetIds];
4927
- const data = await this.requestWithPaymentRaw("/v1/x/tweets/lookup", { tweet_ids: ids });
4928
- return data;
4929
- }
4930
- async xTweetReplies(tweetId, queryType = "Latest", cursor) {
4931
- const body = { tweetId, queryType };
4932
- if (cursor !== void 0) body.cursor = cursor;
4933
- const data = await this.requestWithPaymentRaw("/v1/x/tweets/replies", body);
4934
- return data;
4935
- }
4936
- async xTweetThread(tweetId, cursor) {
4937
- const body = { tweetId };
4938
- if (cursor !== void 0) body.cursor = cursor;
4939
- const data = await this.requestWithPaymentRaw("/v1/x/tweets/thread", body);
4940
- return data;
4941
- }
4942
- async xSearch(query, queryType = "Latest", cursor) {
4943
- const body = { query, queryType };
4944
- if (cursor !== void 0) body.cursor = cursor;
4945
- const data = await this.requestWithPaymentRaw("/v1/x/search", body);
4946
- return data;
4947
- }
4948
- async xTrending() {
4949
- const data = await this.requestWithPaymentRaw("/v1/x/trending", {});
4950
- return data;
4951
- }
4952
- async xArticlesRising() {
4953
- const data = await this.requestWithPaymentRaw("/v1/x/articles/rising", {});
4954
- return data;
4955
- }
4956
- async xAuthorAnalytics(handle) {
4957
- const data = await this.requestWithPaymentRaw("/v1/x/authors", { handle });
4958
- return data;
4959
- }
4960
- async xCompareAuthors(handle1, handle2) {
4961
- const data = await this.requestWithPaymentRaw("/v1/x/compare", { handle1, handle2 });
4962
- return data;
4963
- }
4964
4753
  // ── Prediction Markets (Powered by Predexon) ────────────────────────────
4965
4754
  async pm(path5, params) {
4966
4755
  return this.getWithPaymentRaw(`/v1/pm/${path5}`, params);
@@ -5324,7 +5113,6 @@ var CACHE_DIR = path4.join(os4.homedir(), ".blockrun", "cache");
5324
5113
  var DATA_DIR = path4.join(os4.homedir(), ".blockrun", "data");
5325
5114
  var COST_LOG_FILE2 = path4.join(os4.homedir(), ".blockrun", "cost_log.jsonl");
5326
5115
  var DEFAULT_TTL = {
5327
- "/v1/x/": 3600 * 1e3,
5328
5116
  "/v1/partner/": 3600 * 1e3,
5329
5117
  "/v1/pm/": 1800 * 1e3,
5330
5118
  "/v1/chat/": 0,
@@ -5393,8 +5181,6 @@ function readableFilename(endpoint, body) {
5393
5181
  let ep = endpoint.replace(/\/+$/, "").split("/").pop() || "";
5394
5182
  if (endpoint.includes("/v1/chat/")) {
5395
5183
  ep = "chat";
5396
- } else if (endpoint.includes("/v1/x/")) {
5397
- ep = "x_" + ep;
5398
5184
  } else if (endpoint.includes("/v1/search")) {
5399
5185
  ep = "search";
5400
5186
  } else if (endpoint.includes("/v1/image")) {
@@ -5810,6 +5596,7 @@ var AnthropicClient = class {
5810
5596
  KNOWN_PROVIDERS,
5811
5597
  LLMClient,
5812
5598
  MusicClient,
5599
+ NETWORK_ALIASES,
5813
5600
  OpenAI,
5814
5601
  PHONE_PRICES,
5815
5602
  PORTRAIT_ENROLLMENT_PRICE_USD,
@@ -5817,8 +5604,11 @@ var AnthropicClient = class {
5817
5604
  PhoneClient,
5818
5605
  PortraitClient,
5819
5606
  PriceClient,
5607
+ RPC_PRICE_USD,
5608
+ RpcClient,
5820
5609
  SOLANA_NETWORK,
5821
5610
  SOLANA_WALLET_FILE_PATH,
5611
+ SUPPORTED_NETWORKS,
5822
5612
  SearchClient,
5823
5613
  SolanaLLMClient,
5824
5614
  SpeechClient,
@@ -5830,7 +5620,6 @@ var AnthropicClient = class {
5830
5620
  VoiceClient,
5831
5621
  WALLET_DIR_PATH,
5832
5622
  WALLET_FILE_PATH,
5833
- XClient,
5834
5623
  clearCache,
5835
5624
  createPaymentPayload,
5836
5625
  createSolanaPaymentPayload,