@blockrun/llm 2.5.0 → 2.7.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.js CHANGED
@@ -112,8 +112,8 @@ async function createSolanaPaymentPayload(secretKey, fromAddress, recipient, amo
112
112
  const { Connection, PublicKey, TransactionMessage, VersionedTransaction, ComputeBudgetProgram } = await import("@solana/web3.js");
113
113
  const { getAssociatedTokenAddress, createTransferCheckedInstruction, getMint } = await import("@solana/spl-token");
114
114
  const { Keypair } = await import("@solana/web3.js");
115
- const rpcUrl = options.rpcUrl || "https://api.mainnet-beta.solana.com";
116
- const connection = new Connection(rpcUrl);
115
+ const rpcUrl = options.rpcUrl || "https://sol.blockrun.ai/api/v1/solana/rpc";
116
+ const connection = options.rpcHeaders ? new Connection(rpcUrl, { httpHeaders: options.rpcHeaders }) : new Connection(rpcUrl);
117
117
  const keypair = Keypair.fromSecretKey(secretKey);
118
118
  const feePayerPubkey = new PublicKey(feePayer);
119
119
  const ownerPubkey = keypair.publicKey;
@@ -2310,11 +2310,22 @@ var VideoClient = class {
2310
2310
  * @param options - Optional generation parameters
2311
2311
  */
2312
2312
  async generate(prompt, options) {
2313
+ if (options?.imageUrl && options?.realFaceAssetId) {
2314
+ throw new Error(
2315
+ "imageUrl and realFaceAssetId are mutually exclusive; pass at most one."
2316
+ );
2317
+ }
2318
+ if (options?.realFaceAssetId && !/^ta_[A-Za-z0-9]+$/.test(options.realFaceAssetId)) {
2319
+ throw new Error(
2320
+ "realFaceAssetId must be a Token360 asset id matching 'ta_[A-Za-z0-9]+' (e.g. 'ta_abc123xyz')"
2321
+ );
2322
+ }
2313
2323
  const body = {
2314
2324
  model: options?.model || DEFAULT_MODEL3,
2315
2325
  prompt
2316
2326
  };
2317
2327
  if (options?.imageUrl) body.image_url = options.imageUrl;
2328
+ if (options?.realFaceAssetId) body.real_face_asset_id = options.realFaceAssetId;
2318
2329
  if (options?.durationSeconds !== void 0) body.duration_seconds = options.durationSeconds;
2319
2330
  if (options?.aspectRatio) body.aspect_ratio = options.aspectRatio;
2320
2331
  if (options?.resolution) body.resolution = options.resolution;
@@ -2668,15 +2679,37 @@ var VoiceClient = class {
2668
2679
  }
2669
2680
  };
2670
2681
 
2671
- // src/search.ts
2682
+ // src/phone.ts
2672
2683
  import { privateKeyToAccount as privateKeyToAccount6 } from "viem/accounts";
2673
2684
  var DEFAULT_API_URL6 = "https://blockrun.ai/api";
2674
2685
  var DEFAULT_TIMEOUT6 = 6e4;
2675
- var SearchClient = class {
2686
+ var PHONE_PRICES = Object.freeze({
2687
+ lookup: 0.01,
2688
+ "lookup/fraud": 0.05,
2689
+ "numbers/buy": 5,
2690
+ "numbers/renew": 5,
2691
+ "numbers/list": 1e-3,
2692
+ "numbers/release": 0
2693
+ });
2694
+ function requireE164(value) {
2695
+ if (!value || typeof value !== "string") {
2696
+ throw new Error("phoneNumber is required (E.164 format, e.g. '+14155552671')");
2697
+ }
2698
+ const v = value.trim();
2699
+ if (!/^\+\d{7,15}$/.test(v)) {
2700
+ throw new Error(
2701
+ `phoneNumber must be E.164 (e.g. '+14155552671'), got ${JSON.stringify(value)}`
2702
+ );
2703
+ }
2704
+ return v;
2705
+ }
2706
+ var PhoneClient = class {
2676
2707
  account;
2677
2708
  privateKey;
2678
2709
  apiUrl;
2679
2710
  timeout;
2711
+ sessionTotalUsd = 0;
2712
+ sessionCalls = 0;
2680
2713
  constructor(options = {}) {
2681
2714
  const envKey = typeof process !== "undefined" && process.env ? process.env.BLOCKRUN_WALLET_KEY || process.env.BASE_CHAIN_WALLET_KEY : void 0;
2682
2715
  const privateKey = options.privateKey || envKey;
@@ -2693,6 +2726,203 @@ var SearchClient = class {
2693
2726
  this.apiUrl = apiUrl.replace(/\/$/, "");
2694
2727
  this.timeout = options.timeout || DEFAULT_TIMEOUT6;
2695
2728
  }
2729
+ /** EVM wallet address used for payments. */
2730
+ getWalletAddress() {
2731
+ return this.account.address;
2732
+ }
2733
+ /** Session-cumulative USD spend + call count across this client instance. */
2734
+ getSpending() {
2735
+ return { totalUsd: this.sessionTotalUsd, calls: this.sessionCalls };
2736
+ }
2737
+ // ─── Lookup ────────────────────────────────────────────────────────────
2738
+ /**
2739
+ * Carrier + line-type lookup. ~$0.01.
2740
+ *
2741
+ * @param phoneNumber E.164 number (e.g. "+14155552671").
2742
+ */
2743
+ async lookup(phoneNumber) {
2744
+ const num = requireE164(phoneNumber);
2745
+ return this.request("lookup", { phoneNumber: num });
2746
+ }
2747
+ /**
2748
+ * Lookup + fraud signals (SIM swap, call forwarding). ~$0.05.
2749
+ *
2750
+ * @param phoneNumber E.164 number.
2751
+ */
2752
+ async lookupFraud(phoneNumber) {
2753
+ const num = requireE164(phoneNumber);
2754
+ return this.request("lookup/fraud", { phoneNumber: num });
2755
+ }
2756
+ // ─── Provisioning ──────────────────────────────────────────────────────
2757
+ /**
2758
+ * Provision a dedicated phone number for 30 days. $5.00.
2759
+ *
2760
+ * Payment is settled only after Twilio confirms the purchase, so failed
2761
+ * buys never charge your wallet.
2762
+ *
2763
+ * @param options.country ISO country code, "US" or "CA" (default "US").
2764
+ * @param options.areaCode Optional 3-digit area-code hint. Availability is
2765
+ * not guaranteed — the backend falls back to any number in the country if
2766
+ * the area code can't be matched.
2767
+ */
2768
+ async buyNumber(options = {}) {
2769
+ const country = options.country ?? "US";
2770
+ if (country !== "US" && country !== "CA") {
2771
+ throw new Error("country must be 'US' or 'CA'");
2772
+ }
2773
+ const body = { country };
2774
+ if (options.areaCode !== void 0) {
2775
+ const ac = options.areaCode;
2776
+ if (typeof ac !== "string" || !/^\d{3}$/.test(ac)) {
2777
+ throw new Error("areaCode must be a 3-digit string, e.g. '415'");
2778
+ }
2779
+ body.areaCode = ac;
2780
+ }
2781
+ const data = await this.request("numbers/buy", body);
2782
+ return data;
2783
+ }
2784
+ /**
2785
+ * Extend an existing provisioned number by 30 days. $5.00.
2786
+ *
2787
+ * @throws {APIError} 403 when the wallet doesn't own the number or it has expired.
2788
+ */
2789
+ async renewNumber(phoneNumber) {
2790
+ const num = requireE164(phoneNumber);
2791
+ const data = await this.request("numbers/renew", {
2792
+ phoneNumber: num
2793
+ });
2794
+ return data;
2795
+ }
2796
+ /** List the wallet's active phone numbers. ~$0.001. */
2797
+ async listNumbers() {
2798
+ const data = await this.request("numbers/list", {});
2799
+ return data;
2800
+ }
2801
+ /**
2802
+ * Release a provisioned number back to the Twilio pool. Free, but still
2803
+ * flows through x402 so the backend can verify ownership.
2804
+ */
2805
+ async releaseNumber(phoneNumber) {
2806
+ const num = requireE164(phoneNumber);
2807
+ const data = await this.request("numbers/release", {
2808
+ phoneNumber: num
2809
+ });
2810
+ return data;
2811
+ }
2812
+ // ─── Internals ─────────────────────────────────────────────────────────
2813
+ async request(path5, body) {
2814
+ const url = `${this.apiUrl}/v1/phone/${path5}`;
2815
+ const response = await this.fetchWithTimeout(url, {
2816
+ method: "POST",
2817
+ headers: { "Content-Type": "application/json" },
2818
+ body: JSON.stringify(body)
2819
+ });
2820
+ if (response.status === 402) {
2821
+ return this.handlePaymentAndRetry(url, body, response);
2822
+ }
2823
+ return this.unwrap(response, false);
2824
+ }
2825
+ async handlePaymentAndRetry(url, body, response) {
2826
+ let paymentHeader = response.headers.get("payment-required");
2827
+ if (!paymentHeader) {
2828
+ try {
2829
+ const rb = await response.json();
2830
+ if (rb.x402 || rb.accepts) paymentHeader = btoa(JSON.stringify(rb));
2831
+ } catch {
2832
+ }
2833
+ }
2834
+ if (!paymentHeader) {
2835
+ throw new PaymentError("402 response but no payment requirements found");
2836
+ }
2837
+ const paymentRequired = parsePaymentRequired(paymentHeader);
2838
+ const details = extractPaymentDetails(paymentRequired);
2839
+ const paymentPayload = await createPaymentPayload(
2840
+ this.privateKey,
2841
+ this.account.address,
2842
+ details.recipient,
2843
+ details.amount,
2844
+ details.network || "eip155:8453",
2845
+ {
2846
+ resourceUrl: details.resource?.url || url,
2847
+ resourceDescription: details.resource?.description || "BlockRun Phone",
2848
+ maxTimeoutSeconds: details.maxTimeoutSeconds || 300,
2849
+ extra: details.extra
2850
+ }
2851
+ );
2852
+ const retry = await this.fetchWithTimeout(url, {
2853
+ method: "POST",
2854
+ headers: {
2855
+ "Content-Type": "application/json",
2856
+ "PAYMENT-SIGNATURE": paymentPayload
2857
+ },
2858
+ body: JSON.stringify(body)
2859
+ });
2860
+ if (retry.status === 402) {
2861
+ throw new PaymentError("Payment was rejected. Check your wallet balance.");
2862
+ }
2863
+ const data = await this.unwrap(retry, true);
2864
+ const costUsd = Number.parseFloat(details.amount) / 1e6;
2865
+ this.sessionCalls += 1;
2866
+ this.sessionTotalUsd += costUsd;
2867
+ const txHash = retry.headers.get("x-payment-receipt") || retry.headers.get("X-Payment-Receipt");
2868
+ if (txHash && data && typeof data === "object" && !("txHash" in data)) {
2869
+ data.txHash = txHash;
2870
+ }
2871
+ return data;
2872
+ }
2873
+ async unwrap(response, afterPayment) {
2874
+ if (response.ok) {
2875
+ return response.json();
2876
+ }
2877
+ let errorBody;
2878
+ try {
2879
+ errorBody = await response.json();
2880
+ } catch {
2881
+ errorBody = { error: "Request failed" };
2882
+ }
2883
+ const prefix = afterPayment ? "API error after payment" : "API error";
2884
+ throw new APIError(
2885
+ `${prefix}: ${response.status}`,
2886
+ response.status,
2887
+ sanitizeErrorResponse(errorBody)
2888
+ );
2889
+ }
2890
+ async fetchWithTimeout(url, init) {
2891
+ const controller = new AbortController();
2892
+ const timeoutId = setTimeout(() => controller.abort(), this.timeout);
2893
+ try {
2894
+ return await fetch(url, { ...init, signal: controller.signal });
2895
+ } finally {
2896
+ clearTimeout(timeoutId);
2897
+ }
2898
+ }
2899
+ };
2900
+
2901
+ // src/search.ts
2902
+ import { privateKeyToAccount as privateKeyToAccount7 } from "viem/accounts";
2903
+ var DEFAULT_API_URL7 = "https://blockrun.ai/api";
2904
+ var DEFAULT_TIMEOUT7 = 6e4;
2905
+ var SearchClient = class {
2906
+ account;
2907
+ privateKey;
2908
+ apiUrl;
2909
+ timeout;
2910
+ constructor(options = {}) {
2911
+ const envKey = typeof process !== "undefined" && process.env ? process.env.BLOCKRUN_WALLET_KEY || process.env.BASE_CHAIN_WALLET_KEY : void 0;
2912
+ const privateKey = options.privateKey || envKey;
2913
+ if (!privateKey) {
2914
+ throw new Error(
2915
+ "Private key required. Pass privateKey in options or set BLOCKRUN_WALLET_KEY environment variable."
2916
+ );
2917
+ }
2918
+ validatePrivateKey(privateKey);
2919
+ this.privateKey = privateKey;
2920
+ this.account = privateKeyToAccount7(privateKey);
2921
+ const apiUrl = options.apiUrl || DEFAULT_API_URL7;
2922
+ validateApiUrl(apiUrl);
2923
+ this.apiUrl = apiUrl.replace(/\/$/, "");
2924
+ this.timeout = options.timeout || DEFAULT_TIMEOUT7;
2925
+ }
2696
2926
  async search(query, options) {
2697
2927
  if (!query || query.length > 1e3) {
2698
2928
  throw new Error("query must be 1-1000 characters");
@@ -2805,9 +3035,9 @@ var SearchClient = class {
2805
3035
  };
2806
3036
 
2807
3037
  // src/x-client.ts
2808
- import { privateKeyToAccount as privateKeyToAccount7 } from "viem/accounts";
2809
- var DEFAULT_API_URL7 = "https://blockrun.ai/api";
2810
- var DEFAULT_TIMEOUT7 = 6e4;
3038
+ import { privateKeyToAccount as privateKeyToAccount8 } from "viem/accounts";
3039
+ var DEFAULT_API_URL8 = "https://blockrun.ai/api";
3040
+ var DEFAULT_TIMEOUT8 = 6e4;
2811
3041
  var XClient = class _XClient {
2812
3042
  account;
2813
3043
  privateKey;
@@ -2830,11 +3060,11 @@ var XClient = class _XClient {
2830
3060
  }
2831
3061
  validatePrivateKey(privateKey);
2832
3062
  this.privateKey = privateKey;
2833
- this.account = privateKeyToAccount7(privateKey);
2834
- const apiUrl = options.apiUrl || DEFAULT_API_URL7;
3063
+ this.account = privateKeyToAccount8(privateKey);
3064
+ const apiUrl = options.apiUrl || DEFAULT_API_URL8;
2835
3065
  validateApiUrl(apiUrl);
2836
3066
  this.apiUrl = apiUrl.replace(/\/$/, "");
2837
- this.timeout = options.timeout || DEFAULT_TIMEOUT7;
3067
+ this.timeout = options.timeout || DEFAULT_TIMEOUT8;
2838
3068
  }
2839
3069
  // ───────── User endpoints ─────────
2840
3070
  userLookup(usernames) {
@@ -3012,9 +3242,9 @@ var XClient = class _XClient {
3012
3242
  };
3013
3243
 
3014
3244
  // src/price.ts
3015
- import { privateKeyToAccount as privateKeyToAccount8 } from "viem/accounts";
3016
- var DEFAULT_API_URL8 = "https://blockrun.ai/api";
3017
- var DEFAULT_TIMEOUT8 = 3e4;
3245
+ import { privateKeyToAccount as privateKeyToAccount9 } from "viem/accounts";
3246
+ var DEFAULT_API_URL9 = "https://blockrun.ai/api";
3247
+ var DEFAULT_TIMEOUT9 = 3e4;
3018
3248
  var PriceClient = class {
3019
3249
  account = null;
3020
3250
  privateKey = null;
@@ -3032,12 +3262,12 @@ var PriceClient = class {
3032
3262
  if (privateKey) {
3033
3263
  validatePrivateKey(privateKey);
3034
3264
  this.privateKey = privateKey;
3035
- this.account = privateKeyToAccount8(privateKey);
3265
+ this.account = privateKeyToAccount9(privateKey);
3036
3266
  }
3037
- const apiUrl = options.apiUrl || DEFAULT_API_URL8;
3267
+ const apiUrl = options.apiUrl || DEFAULT_API_URL9;
3038
3268
  validateApiUrl(apiUrl);
3039
3269
  this.apiUrl = apiUrl.replace(/\/$/, "");
3040
- this.timeout = options.timeout || DEFAULT_TIMEOUT8;
3270
+ this.timeout = options.timeout || DEFAULT_TIMEOUT9;
3041
3271
  }
3042
3272
  async price(category, symbol, options) {
3043
3273
  if (!symbol) throw new Error("symbol is required");
@@ -3216,9 +3446,9 @@ function buildUrl(base, query) {
3216
3446
  }
3217
3447
 
3218
3448
  // src/surf.ts
3219
- import { privateKeyToAccount as privateKeyToAccount9 } from "viem/accounts";
3220
- var DEFAULT_API_URL9 = "https://blockrun.ai/api";
3221
- var DEFAULT_TIMEOUT9 = 6e4;
3449
+ import { privateKeyToAccount as privateKeyToAccount10 } from "viem/accounts";
3450
+ var DEFAULT_API_URL10 = "https://blockrun.ai/api";
3451
+ var DEFAULT_TIMEOUT10 = 6e4;
3222
3452
  var SURF_PREFIX = "/v1/surf";
3223
3453
  var SurfClient = class {
3224
3454
  account;
@@ -3235,11 +3465,11 @@ var SurfClient = class {
3235
3465
  }
3236
3466
  validatePrivateKey(privateKey);
3237
3467
  this.privateKey = privateKey;
3238
- this.account = privateKeyToAccount9(privateKey);
3239
- const apiUrl = options.apiUrl || DEFAULT_API_URL9;
3468
+ this.account = privateKeyToAccount10(privateKey);
3469
+ const apiUrl = options.apiUrl || DEFAULT_API_URL10;
3240
3470
  validateApiUrl(apiUrl);
3241
3471
  this.apiUrl = apiUrl.replace(/\/$/, "");
3242
- this.timeout = options.timeout || DEFAULT_TIMEOUT9;
3472
+ this.timeout = options.timeout || DEFAULT_TIMEOUT10;
3243
3473
  }
3244
3474
  /**
3245
3475
  * GET a Surf endpoint. `path` is everything after `/v1/surf` (a leading
@@ -3371,9 +3601,9 @@ var SurfClient = class {
3371
3601
  };
3372
3602
 
3373
3603
  // src/blockrun.ts
3374
- import { privateKeyToAccount as privateKeyToAccount10 } from "viem/accounts";
3375
- var DEFAULT_API_URL10 = "https://blockrun.ai/api";
3376
- var DEFAULT_TIMEOUT10 = 6e4;
3604
+ import { privateKeyToAccount as privateKeyToAccount11 } from "viem/accounts";
3605
+ var DEFAULT_API_URL11 = "https://blockrun.ai/api";
3606
+ var DEFAULT_TIMEOUT11 = 6e4;
3377
3607
  var DEFAULT_POLL_INTERVAL_MS = 5e3;
3378
3608
  var DEFAULT_POLL_BUDGET_MS = 3e5;
3379
3609
  var MAX_SIGNED_AUTH_SECONDS = 600;
@@ -3394,11 +3624,11 @@ var BlockrunClient = class {
3394
3624
  }
3395
3625
  validatePrivateKey(privateKey);
3396
3626
  this.privateKey = privateKey;
3397
- this.account = privateKeyToAccount10(privateKey);
3398
- const apiUrl = options.apiUrl || DEFAULT_API_URL10;
3627
+ this.account = privateKeyToAccount11(privateKey);
3628
+ const apiUrl = options.apiUrl || DEFAULT_API_URL11;
3399
3629
  validateApiUrl(apiUrl);
3400
3630
  this.apiUrl = apiUrl.replace(/\/$/, "");
3401
- this.timeout = options.timeout || DEFAULT_TIMEOUT10;
3631
+ this.timeout = options.timeout || DEFAULT_TIMEOUT11;
3402
3632
  }
3403
3633
  /**
3404
3634
  * GET a BlockRun endpoint. `path` is everything after `/api` (a leading
@@ -3749,7 +3979,7 @@ function sleep(ms) {
3749
3979
  }
3750
3980
 
3751
3981
  // src/wallet.ts
3752
- import { privateKeyToAccount as privateKeyToAccount11, generatePrivateKey } from "viem/accounts";
3982
+ import { privateKeyToAccount as privateKeyToAccount12, generatePrivateKey } from "viem/accounts";
3753
3983
  import * as fs2 from "fs";
3754
3984
  import * as path2 from "path";
3755
3985
  import * as os2 from "os";
@@ -3759,7 +3989,7 @@ var WALLET_DIR = path2.join(os2.homedir(), ".blockrun");
3759
3989
  var WALLET_FILE = path2.join(WALLET_DIR, ".session");
3760
3990
  function createWallet() {
3761
3991
  const privateKey = generatePrivateKey();
3762
- const account = privateKeyToAccount11(privateKey);
3992
+ const account = privateKeyToAccount12(privateKey);
3763
3993
  return {
3764
3994
  address: account.address,
3765
3995
  privateKey
@@ -3815,12 +4045,12 @@ function loadWallet() {
3815
4045
  function getOrCreateWallet() {
3816
4046
  const envKey = typeof process !== "undefined" && process.env ? process.env.BLOCKRUN_WALLET_KEY || process.env.BASE_CHAIN_WALLET_KEY : void 0;
3817
4047
  if (envKey) {
3818
- const account = privateKeyToAccount11(envKey);
4048
+ const account = privateKeyToAccount12(envKey);
3819
4049
  return { address: account.address, privateKey: envKey, isNew: false };
3820
4050
  }
3821
4051
  const fileKey = loadWallet();
3822
4052
  if (fileKey) {
3823
- const account = privateKeyToAccount11(fileKey);
4053
+ const account = privateKeyToAccount12(fileKey);
3824
4054
  return { address: account.address, privateKey: fileKey, isNew: false };
3825
4055
  }
3826
4056
  const { address, privateKey } = createWallet();
@@ -3830,11 +4060,11 @@ function getOrCreateWallet() {
3830
4060
  function getWalletAddress() {
3831
4061
  const envKey = typeof process !== "undefined" && process.env ? process.env.BLOCKRUN_WALLET_KEY || process.env.BASE_CHAIN_WALLET_KEY : void 0;
3832
4062
  if (envKey) {
3833
- return privateKeyToAccount11(envKey).address;
4063
+ return privateKeyToAccount12(envKey).address;
3834
4064
  }
3835
4065
  const fileKey = loadWallet();
3836
4066
  if (fileKey) {
3837
- return privateKeyToAccount11(fileKey).address;
4067
+ return privateKeyToAccount12(fileKey).address;
3838
4068
  }
3839
4069
  return null;
3840
4070
  }
@@ -4014,14 +4244,37 @@ async function getOrCreateSolanaWallet() {
4014
4244
  // src/solana-client.ts
4015
4245
  var SOLANA_API_URL = "https://sol.blockrun.ai/api";
4016
4246
  var DEFAULT_MAX_TOKENS2 = 1024;
4017
- var DEFAULT_TIMEOUT11 = 6e4;
4247
+ var DEFAULT_TIMEOUT12 = 6e4;
4018
4248
  var SDK_VERSION2 = "0.3.0";
4019
4249
  var USER_AGENT2 = `blockrun-ts/${SDK_VERSION2}`;
4250
+ var DEFAULT_SOLANA_RPC_URL = "https://sol.blockrun.ai/api/v1/solana/rpc";
4251
+ function resolveRpcConfig(rpcUrl, rpcHeaders) {
4252
+ const env = typeof process !== "undefined" && process.env ? process.env : {};
4253
+ const url = rpcUrl || env.SOLANA_RPC_URL || DEFAULT_SOLANA_RPC_URL;
4254
+ let headers;
4255
+ if (rpcHeaders) {
4256
+ headers = { ...rpcHeaders };
4257
+ } else if (env.SOLANA_RPC_HEADERS) {
4258
+ try {
4259
+ const parsed = JSON.parse(env.SOLANA_RPC_HEADERS);
4260
+ if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
4261
+ headers = Object.fromEntries(
4262
+ Object.entries(parsed).map(([k, v]) => [String(k), String(v)])
4263
+ );
4264
+ }
4265
+ } catch {
4266
+ }
4267
+ } else if (env.SOLANA_RPC_API_KEY) {
4268
+ headers = { "x-api-key": env.SOLANA_RPC_API_KEY };
4269
+ }
4270
+ return headers ? { url, headers } : { url };
4271
+ }
4020
4272
  var SolanaLLMClient = class {
4021
4273
  static SOLANA_API_URL = SOLANA_API_URL;
4022
4274
  privateKey;
4023
4275
  apiUrl;
4024
4276
  rpcUrl;
4277
+ rpcHeaders;
4025
4278
  timeout;
4026
4279
  sessionTotalUsd = 0;
4027
4280
  sessionCalls = 0;
@@ -4038,8 +4291,10 @@ var SolanaLLMClient = class {
4038
4291
  const apiUrl = options.apiUrl || SOLANA_API_URL;
4039
4292
  validateApiUrl(apiUrl);
4040
4293
  this.apiUrl = apiUrl.replace(/\/$/, "");
4041
- this.rpcUrl = options.rpcUrl || "https://api.mainnet-beta.solana.com";
4042
- this.timeout = options.timeout || DEFAULT_TIMEOUT11;
4294
+ const rpc = resolveRpcConfig(options.rpcUrl, options.rpcHeaders);
4295
+ this.rpcUrl = rpc.url;
4296
+ this.rpcHeaders = rpc.headers;
4297
+ this.timeout = options.timeout || DEFAULT_TIMEOUT12;
4043
4298
  }
4044
4299
  /** Get Solana wallet address (public key in base58). */
4045
4300
  async getWalletAddress() {
@@ -4097,7 +4352,7 @@ var SolanaLLMClient = class {
4097
4352
  try {
4098
4353
  const response = await fetch(this.rpcUrl, {
4099
4354
  method: "POST",
4100
- headers: { "Content-Type": "application/json" },
4355
+ headers: { "Content-Type": "application/json", ...this.rpcHeaders ?? {} },
4101
4356
  body: JSON.stringify({
4102
4357
  jsonrpc: "2.0",
4103
4358
  id: 1,
@@ -4348,7 +4603,8 @@ var SolanaLLMClient = class {
4348
4603
  maxTimeoutSeconds: details.maxTimeoutSeconds || 300,
4349
4604
  extra: details.extra,
4350
4605
  extensions,
4351
- rpcUrl: this.rpcUrl
4606
+ rpcUrl: this.rpcUrl,
4607
+ rpcHeaders: this.rpcHeaders
4352
4608
  }
4353
4609
  );
4354
4610
  const retryResponse = await this.fetchWithTimeout(url, {
@@ -4439,7 +4695,8 @@ var SolanaLLMClient = class {
4439
4695
  maxTimeoutSeconds: details.maxTimeoutSeconds || 300,
4440
4696
  extra: details.extra,
4441
4697
  extensions,
4442
- rpcUrl: this.rpcUrl
4698
+ rpcUrl: this.rpcUrl,
4699
+ rpcHeaders: this.rpcHeaders
4443
4700
  }
4444
4701
  );
4445
4702
  const retryResponse = await this.fetchWithTimeout(url, {
@@ -4530,7 +4787,8 @@ var SolanaLLMClient = class {
4530
4787
  maxTimeoutSeconds: details.maxTimeoutSeconds || 300,
4531
4788
  extra: details.extra,
4532
4789
  extensions,
4533
- rpcUrl: this.rpcUrl
4790
+ rpcUrl: this.rpcUrl,
4791
+ rpcHeaders: this.rpcHeaders
4534
4792
  }
4535
4793
  );
4536
4794
  const query = params ? "?" + new URLSearchParams(params).toString() : "";
@@ -4946,7 +5204,7 @@ var OpenAI = class {
4946
5204
  };
4947
5205
 
4948
5206
  // src/anthropic-compat.ts
4949
- import { privateKeyToAccount as privateKeyToAccount12 } from "viem/accounts";
5207
+ import { privateKeyToAccount as privateKeyToAccount13 } from "viem/accounts";
4950
5208
  var AnthropicClient = class {
4951
5209
  _client = null;
4952
5210
  _clientPromise = null;
@@ -4959,7 +5217,7 @@ var AnthropicClient = class {
4959
5217
  const key = options.privateKey ?? wallet.privateKey;
4960
5218
  validatePrivateKey(key);
4961
5219
  this._privateKey = key;
4962
- this._account = privateKeyToAccount12(this._privateKey);
5220
+ this._account = privateKeyToAccount13(this._privateKey);
4963
5221
  const apiUrl = options.apiUrl ?? "https://blockrun.ai/api";
4964
5222
  validateApiUrl(apiUrl);
4965
5223
  this._apiUrl = apiUrl.replace(/\/$/, "");
@@ -5064,7 +5322,9 @@ export {
5064
5322
  LLMClient,
5065
5323
  MusicClient,
5066
5324
  OpenAI,
5325
+ PHONE_PRICES,
5067
5326
  PaymentError,
5327
+ PhoneClient,
5068
5328
  PriceClient,
5069
5329
  SOLANA_NETWORK,
5070
5330
  SOLANA_WALLET_FILE as SOLANA_WALLET_FILE_PATH,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@blockrun/llm",
3
- "version": "2.5.0",
3
+ "version": "2.7.0",
4
4
  "type": "module",
5
5
  "description": "BlockRun SDK - Pay-per-request AI (LLM, Image, Video, Music, Voice) via x402 on Base and Solana",
6
6
  "main": "dist/index.cjs",