@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.cjs CHANGED
@@ -40,7 +40,9 @@ __export(index_exports, {
40
40
  LLMClient: () => LLMClient,
41
41
  MusicClient: () => MusicClient,
42
42
  OpenAI: () => OpenAI,
43
+ PHONE_PRICES: () => PHONE_PRICES,
43
44
  PaymentError: () => PaymentError,
45
+ PhoneClient: () => PhoneClient,
44
46
  PriceClient: () => PriceClient,
45
47
  SOLANA_NETWORK: () => SOLANA_NETWORK,
46
48
  SOLANA_WALLET_FILE_PATH: () => SOLANA_WALLET_FILE,
@@ -211,8 +213,8 @@ async function createSolanaPaymentPayload(secretKey, fromAddress, recipient, amo
211
213
  const { Connection, PublicKey, TransactionMessage, VersionedTransaction, ComputeBudgetProgram } = await import("@solana/web3.js");
212
214
  const { getAssociatedTokenAddress, createTransferCheckedInstruction, getMint } = await import("@solana/spl-token");
213
215
  const { Keypair } = await import("@solana/web3.js");
214
- const rpcUrl = options.rpcUrl || "https://api.mainnet-beta.solana.com";
215
- const connection = new Connection(rpcUrl);
216
+ const rpcUrl = options.rpcUrl || "https://sol.blockrun.ai/api/v1/solana/rpc";
217
+ const connection = options.rpcHeaders ? new Connection(rpcUrl, { httpHeaders: options.rpcHeaders }) : new Connection(rpcUrl);
216
218
  const keypair = Keypair.fromSecretKey(secretKey);
217
219
  const feePayerPubkey = new PublicKey(feePayer);
218
220
  const ownerPubkey = keypair.publicKey;
@@ -2409,11 +2411,22 @@ var VideoClient = class {
2409
2411
  * @param options - Optional generation parameters
2410
2412
  */
2411
2413
  async generate(prompt, options) {
2414
+ if (options?.imageUrl && options?.realFaceAssetId) {
2415
+ throw new Error(
2416
+ "imageUrl and realFaceAssetId are mutually exclusive; pass at most one."
2417
+ );
2418
+ }
2419
+ if (options?.realFaceAssetId && !/^ta_[A-Za-z0-9]+$/.test(options.realFaceAssetId)) {
2420
+ throw new Error(
2421
+ "realFaceAssetId must be a Token360 asset id matching 'ta_[A-Za-z0-9]+' (e.g. 'ta_abc123xyz')"
2422
+ );
2423
+ }
2412
2424
  const body = {
2413
2425
  model: options?.model || DEFAULT_MODEL3,
2414
2426
  prompt
2415
2427
  };
2416
2428
  if (options?.imageUrl) body.image_url = options.imageUrl;
2429
+ if (options?.realFaceAssetId) body.real_face_asset_id = options.realFaceAssetId;
2417
2430
  if (options?.durationSeconds !== void 0) body.duration_seconds = options.durationSeconds;
2418
2431
  if (options?.aspectRatio) body.aspect_ratio = options.aspectRatio;
2419
2432
  if (options?.resolution) body.resolution = options.resolution;
@@ -2767,15 +2780,37 @@ var VoiceClient = class {
2767
2780
  }
2768
2781
  };
2769
2782
 
2770
- // src/search.ts
2783
+ // src/phone.ts
2771
2784
  var import_accounts7 = require("viem/accounts");
2772
2785
  var DEFAULT_API_URL6 = "https://blockrun.ai/api";
2773
2786
  var DEFAULT_TIMEOUT6 = 6e4;
2774
- var SearchClient = class {
2787
+ var PHONE_PRICES = Object.freeze({
2788
+ lookup: 0.01,
2789
+ "lookup/fraud": 0.05,
2790
+ "numbers/buy": 5,
2791
+ "numbers/renew": 5,
2792
+ "numbers/list": 1e-3,
2793
+ "numbers/release": 0
2794
+ });
2795
+ function requireE164(value) {
2796
+ if (!value || typeof value !== "string") {
2797
+ throw new Error("phoneNumber is required (E.164 format, e.g. '+14155552671')");
2798
+ }
2799
+ const v = value.trim();
2800
+ if (!/^\+\d{7,15}$/.test(v)) {
2801
+ throw new Error(
2802
+ `phoneNumber must be E.164 (e.g. '+14155552671'), got ${JSON.stringify(value)}`
2803
+ );
2804
+ }
2805
+ return v;
2806
+ }
2807
+ var PhoneClient = class {
2775
2808
  account;
2776
2809
  privateKey;
2777
2810
  apiUrl;
2778
2811
  timeout;
2812
+ sessionTotalUsd = 0;
2813
+ sessionCalls = 0;
2779
2814
  constructor(options = {}) {
2780
2815
  const envKey = typeof process !== "undefined" && process.env ? process.env.BLOCKRUN_WALLET_KEY || process.env.BASE_CHAIN_WALLET_KEY : void 0;
2781
2816
  const privateKey = options.privateKey || envKey;
@@ -2792,6 +2827,203 @@ var SearchClient = class {
2792
2827
  this.apiUrl = apiUrl.replace(/\/$/, "");
2793
2828
  this.timeout = options.timeout || DEFAULT_TIMEOUT6;
2794
2829
  }
2830
+ /** EVM wallet address used for payments. */
2831
+ getWalletAddress() {
2832
+ return this.account.address;
2833
+ }
2834
+ /** Session-cumulative USD spend + call count across this client instance. */
2835
+ getSpending() {
2836
+ return { totalUsd: this.sessionTotalUsd, calls: this.sessionCalls };
2837
+ }
2838
+ // ─── Lookup ────────────────────────────────────────────────────────────
2839
+ /**
2840
+ * Carrier + line-type lookup. ~$0.01.
2841
+ *
2842
+ * @param phoneNumber E.164 number (e.g. "+14155552671").
2843
+ */
2844
+ async lookup(phoneNumber) {
2845
+ const num = requireE164(phoneNumber);
2846
+ return this.request("lookup", { phoneNumber: num });
2847
+ }
2848
+ /**
2849
+ * Lookup + fraud signals (SIM swap, call forwarding). ~$0.05.
2850
+ *
2851
+ * @param phoneNumber E.164 number.
2852
+ */
2853
+ async lookupFraud(phoneNumber) {
2854
+ const num = requireE164(phoneNumber);
2855
+ return this.request("lookup/fraud", { phoneNumber: num });
2856
+ }
2857
+ // ─── Provisioning ──────────────────────────────────────────────────────
2858
+ /**
2859
+ * Provision a dedicated phone number for 30 days. $5.00.
2860
+ *
2861
+ * Payment is settled only after Twilio confirms the purchase, so failed
2862
+ * buys never charge your wallet.
2863
+ *
2864
+ * @param options.country ISO country code, "US" or "CA" (default "US").
2865
+ * @param options.areaCode Optional 3-digit area-code hint. Availability is
2866
+ * not guaranteed — the backend falls back to any number in the country if
2867
+ * the area code can't be matched.
2868
+ */
2869
+ async buyNumber(options = {}) {
2870
+ const country = options.country ?? "US";
2871
+ if (country !== "US" && country !== "CA") {
2872
+ throw new Error("country must be 'US' or 'CA'");
2873
+ }
2874
+ const body = { country };
2875
+ if (options.areaCode !== void 0) {
2876
+ const ac = options.areaCode;
2877
+ if (typeof ac !== "string" || !/^\d{3}$/.test(ac)) {
2878
+ throw new Error("areaCode must be a 3-digit string, e.g. '415'");
2879
+ }
2880
+ body.areaCode = ac;
2881
+ }
2882
+ const data = await this.request("numbers/buy", body);
2883
+ return data;
2884
+ }
2885
+ /**
2886
+ * Extend an existing provisioned number by 30 days. $5.00.
2887
+ *
2888
+ * @throws {APIError} 403 when the wallet doesn't own the number or it has expired.
2889
+ */
2890
+ async renewNumber(phoneNumber) {
2891
+ const num = requireE164(phoneNumber);
2892
+ const data = await this.request("numbers/renew", {
2893
+ phoneNumber: num
2894
+ });
2895
+ return data;
2896
+ }
2897
+ /** List the wallet's active phone numbers. ~$0.001. */
2898
+ async listNumbers() {
2899
+ const data = await this.request("numbers/list", {});
2900
+ return data;
2901
+ }
2902
+ /**
2903
+ * Release a provisioned number back to the Twilio pool. Free, but still
2904
+ * flows through x402 so the backend can verify ownership.
2905
+ */
2906
+ async releaseNumber(phoneNumber) {
2907
+ const num = requireE164(phoneNumber);
2908
+ const data = await this.request("numbers/release", {
2909
+ phoneNumber: num
2910
+ });
2911
+ return data;
2912
+ }
2913
+ // ─── Internals ─────────────────────────────────────────────────────────
2914
+ async request(path5, body) {
2915
+ const url = `${this.apiUrl}/v1/phone/${path5}`;
2916
+ const response = await this.fetchWithTimeout(url, {
2917
+ method: "POST",
2918
+ headers: { "Content-Type": "application/json" },
2919
+ body: JSON.stringify(body)
2920
+ });
2921
+ if (response.status === 402) {
2922
+ return this.handlePaymentAndRetry(url, body, response);
2923
+ }
2924
+ return this.unwrap(response, false);
2925
+ }
2926
+ async handlePaymentAndRetry(url, body, response) {
2927
+ let paymentHeader = response.headers.get("payment-required");
2928
+ if (!paymentHeader) {
2929
+ try {
2930
+ const rb = await response.json();
2931
+ if (rb.x402 || rb.accepts) paymentHeader = btoa(JSON.stringify(rb));
2932
+ } catch {
2933
+ }
2934
+ }
2935
+ if (!paymentHeader) {
2936
+ throw new PaymentError("402 response but no payment requirements found");
2937
+ }
2938
+ const paymentRequired = parsePaymentRequired(paymentHeader);
2939
+ const details = extractPaymentDetails(paymentRequired);
2940
+ const paymentPayload = await createPaymentPayload(
2941
+ this.privateKey,
2942
+ this.account.address,
2943
+ details.recipient,
2944
+ details.amount,
2945
+ details.network || "eip155:8453",
2946
+ {
2947
+ resourceUrl: details.resource?.url || url,
2948
+ resourceDescription: details.resource?.description || "BlockRun Phone",
2949
+ maxTimeoutSeconds: details.maxTimeoutSeconds || 300,
2950
+ extra: details.extra
2951
+ }
2952
+ );
2953
+ const retry = await this.fetchWithTimeout(url, {
2954
+ method: "POST",
2955
+ headers: {
2956
+ "Content-Type": "application/json",
2957
+ "PAYMENT-SIGNATURE": paymentPayload
2958
+ },
2959
+ body: JSON.stringify(body)
2960
+ });
2961
+ if (retry.status === 402) {
2962
+ throw new PaymentError("Payment was rejected. Check your wallet balance.");
2963
+ }
2964
+ const data = await this.unwrap(retry, true);
2965
+ const costUsd = Number.parseFloat(details.amount) / 1e6;
2966
+ this.sessionCalls += 1;
2967
+ this.sessionTotalUsd += costUsd;
2968
+ const txHash = retry.headers.get("x-payment-receipt") || retry.headers.get("X-Payment-Receipt");
2969
+ if (txHash && data && typeof data === "object" && !("txHash" in data)) {
2970
+ data.txHash = txHash;
2971
+ }
2972
+ return data;
2973
+ }
2974
+ async unwrap(response, afterPayment) {
2975
+ if (response.ok) {
2976
+ return response.json();
2977
+ }
2978
+ let errorBody;
2979
+ try {
2980
+ errorBody = await response.json();
2981
+ } catch {
2982
+ errorBody = { error: "Request failed" };
2983
+ }
2984
+ const prefix = afterPayment ? "API error after payment" : "API error";
2985
+ throw new APIError(
2986
+ `${prefix}: ${response.status}`,
2987
+ response.status,
2988
+ sanitizeErrorResponse(errorBody)
2989
+ );
2990
+ }
2991
+ async fetchWithTimeout(url, init) {
2992
+ const controller = new AbortController();
2993
+ const timeoutId = setTimeout(() => controller.abort(), this.timeout);
2994
+ try {
2995
+ return await fetch(url, { ...init, signal: controller.signal });
2996
+ } finally {
2997
+ clearTimeout(timeoutId);
2998
+ }
2999
+ }
3000
+ };
3001
+
3002
+ // src/search.ts
3003
+ var import_accounts8 = require("viem/accounts");
3004
+ var DEFAULT_API_URL7 = "https://blockrun.ai/api";
3005
+ var DEFAULT_TIMEOUT7 = 6e4;
3006
+ var SearchClient = class {
3007
+ account;
3008
+ privateKey;
3009
+ apiUrl;
3010
+ timeout;
3011
+ constructor(options = {}) {
3012
+ const envKey = typeof process !== "undefined" && process.env ? process.env.BLOCKRUN_WALLET_KEY || process.env.BASE_CHAIN_WALLET_KEY : void 0;
3013
+ const privateKey = options.privateKey || envKey;
3014
+ if (!privateKey) {
3015
+ throw new Error(
3016
+ "Private key required. Pass privateKey in options or set BLOCKRUN_WALLET_KEY environment variable."
3017
+ );
3018
+ }
3019
+ validatePrivateKey(privateKey);
3020
+ this.privateKey = privateKey;
3021
+ this.account = (0, import_accounts8.privateKeyToAccount)(privateKey);
3022
+ const apiUrl = options.apiUrl || DEFAULT_API_URL7;
3023
+ validateApiUrl(apiUrl);
3024
+ this.apiUrl = apiUrl.replace(/\/$/, "");
3025
+ this.timeout = options.timeout || DEFAULT_TIMEOUT7;
3026
+ }
2795
3027
  async search(query, options) {
2796
3028
  if (!query || query.length > 1e3) {
2797
3029
  throw new Error("query must be 1-1000 characters");
@@ -2904,9 +3136,9 @@ var SearchClient = class {
2904
3136
  };
2905
3137
 
2906
3138
  // src/x-client.ts
2907
- var import_accounts8 = require("viem/accounts");
2908
- var DEFAULT_API_URL7 = "https://blockrun.ai/api";
2909
- var DEFAULT_TIMEOUT7 = 6e4;
3139
+ var import_accounts9 = require("viem/accounts");
3140
+ var DEFAULT_API_URL8 = "https://blockrun.ai/api";
3141
+ var DEFAULT_TIMEOUT8 = 6e4;
2910
3142
  var XClient = class _XClient {
2911
3143
  account;
2912
3144
  privateKey;
@@ -2929,11 +3161,11 @@ var XClient = class _XClient {
2929
3161
  }
2930
3162
  validatePrivateKey(privateKey);
2931
3163
  this.privateKey = privateKey;
2932
- this.account = (0, import_accounts8.privateKeyToAccount)(privateKey);
2933
- const apiUrl = options.apiUrl || DEFAULT_API_URL7;
3164
+ this.account = (0, import_accounts9.privateKeyToAccount)(privateKey);
3165
+ const apiUrl = options.apiUrl || DEFAULT_API_URL8;
2934
3166
  validateApiUrl(apiUrl);
2935
3167
  this.apiUrl = apiUrl.replace(/\/$/, "");
2936
- this.timeout = options.timeout || DEFAULT_TIMEOUT7;
3168
+ this.timeout = options.timeout || DEFAULT_TIMEOUT8;
2937
3169
  }
2938
3170
  // ───────── User endpoints ─────────
2939
3171
  userLookup(usernames) {
@@ -3111,9 +3343,9 @@ var XClient = class _XClient {
3111
3343
  };
3112
3344
 
3113
3345
  // src/price.ts
3114
- var import_accounts9 = require("viem/accounts");
3115
- var DEFAULT_API_URL8 = "https://blockrun.ai/api";
3116
- var DEFAULT_TIMEOUT8 = 3e4;
3346
+ var import_accounts10 = require("viem/accounts");
3347
+ var DEFAULT_API_URL9 = "https://blockrun.ai/api";
3348
+ var DEFAULT_TIMEOUT9 = 3e4;
3117
3349
  var PriceClient = class {
3118
3350
  account = null;
3119
3351
  privateKey = null;
@@ -3131,12 +3363,12 @@ var PriceClient = class {
3131
3363
  if (privateKey) {
3132
3364
  validatePrivateKey(privateKey);
3133
3365
  this.privateKey = privateKey;
3134
- this.account = (0, import_accounts9.privateKeyToAccount)(privateKey);
3366
+ this.account = (0, import_accounts10.privateKeyToAccount)(privateKey);
3135
3367
  }
3136
- const apiUrl = options.apiUrl || DEFAULT_API_URL8;
3368
+ const apiUrl = options.apiUrl || DEFAULT_API_URL9;
3137
3369
  validateApiUrl(apiUrl);
3138
3370
  this.apiUrl = apiUrl.replace(/\/$/, "");
3139
- this.timeout = options.timeout || DEFAULT_TIMEOUT8;
3371
+ this.timeout = options.timeout || DEFAULT_TIMEOUT9;
3140
3372
  }
3141
3373
  async price(category, symbol, options) {
3142
3374
  if (!symbol) throw new Error("symbol is required");
@@ -3315,9 +3547,9 @@ function buildUrl(base, query) {
3315
3547
  }
3316
3548
 
3317
3549
  // src/surf.ts
3318
- var import_accounts10 = require("viem/accounts");
3319
- var DEFAULT_API_URL9 = "https://blockrun.ai/api";
3320
- var DEFAULT_TIMEOUT9 = 6e4;
3550
+ var import_accounts11 = require("viem/accounts");
3551
+ var DEFAULT_API_URL10 = "https://blockrun.ai/api";
3552
+ var DEFAULT_TIMEOUT10 = 6e4;
3321
3553
  var SURF_PREFIX = "/v1/surf";
3322
3554
  var SurfClient = class {
3323
3555
  account;
@@ -3334,11 +3566,11 @@ var SurfClient = class {
3334
3566
  }
3335
3567
  validatePrivateKey(privateKey);
3336
3568
  this.privateKey = privateKey;
3337
- this.account = (0, import_accounts10.privateKeyToAccount)(privateKey);
3338
- const apiUrl = options.apiUrl || DEFAULT_API_URL9;
3569
+ this.account = (0, import_accounts11.privateKeyToAccount)(privateKey);
3570
+ const apiUrl = options.apiUrl || DEFAULT_API_URL10;
3339
3571
  validateApiUrl(apiUrl);
3340
3572
  this.apiUrl = apiUrl.replace(/\/$/, "");
3341
- this.timeout = options.timeout || DEFAULT_TIMEOUT9;
3573
+ this.timeout = options.timeout || DEFAULT_TIMEOUT10;
3342
3574
  }
3343
3575
  /**
3344
3576
  * GET a Surf endpoint. `path` is everything after `/v1/surf` (a leading
@@ -3470,9 +3702,9 @@ var SurfClient = class {
3470
3702
  };
3471
3703
 
3472
3704
  // src/blockrun.ts
3473
- var import_accounts11 = require("viem/accounts");
3474
- var DEFAULT_API_URL10 = "https://blockrun.ai/api";
3475
- var DEFAULT_TIMEOUT10 = 6e4;
3705
+ var import_accounts12 = require("viem/accounts");
3706
+ var DEFAULT_API_URL11 = "https://blockrun.ai/api";
3707
+ var DEFAULT_TIMEOUT11 = 6e4;
3476
3708
  var DEFAULT_POLL_INTERVAL_MS = 5e3;
3477
3709
  var DEFAULT_POLL_BUDGET_MS = 3e5;
3478
3710
  var MAX_SIGNED_AUTH_SECONDS = 600;
@@ -3493,11 +3725,11 @@ var BlockrunClient = class {
3493
3725
  }
3494
3726
  validatePrivateKey(privateKey);
3495
3727
  this.privateKey = privateKey;
3496
- this.account = (0, import_accounts11.privateKeyToAccount)(privateKey);
3497
- const apiUrl = options.apiUrl || DEFAULT_API_URL10;
3728
+ this.account = (0, import_accounts12.privateKeyToAccount)(privateKey);
3729
+ const apiUrl = options.apiUrl || DEFAULT_API_URL11;
3498
3730
  validateApiUrl(apiUrl);
3499
3731
  this.apiUrl = apiUrl.replace(/\/$/, "");
3500
- this.timeout = options.timeout || DEFAULT_TIMEOUT10;
3732
+ this.timeout = options.timeout || DEFAULT_TIMEOUT11;
3501
3733
  }
3502
3734
  /**
3503
3735
  * GET a BlockRun endpoint. `path` is everything after `/api` (a leading
@@ -3848,7 +4080,7 @@ function sleep(ms) {
3848
4080
  }
3849
4081
 
3850
4082
  // src/wallet.ts
3851
- var import_accounts12 = require("viem/accounts");
4083
+ var import_accounts13 = require("viem/accounts");
3852
4084
  var fs2 = __toESM(require("fs"), 1);
3853
4085
  var path2 = __toESM(require("path"), 1);
3854
4086
  var os2 = __toESM(require("os"), 1);
@@ -3857,8 +4089,8 @@ var BASE_CHAIN_ID2 = "8453";
3857
4089
  var WALLET_DIR = path2.join(os2.homedir(), ".blockrun");
3858
4090
  var WALLET_FILE = path2.join(WALLET_DIR, ".session");
3859
4091
  function createWallet() {
3860
- const privateKey = (0, import_accounts12.generatePrivateKey)();
3861
- const account = (0, import_accounts12.privateKeyToAccount)(privateKey);
4092
+ const privateKey = (0, import_accounts13.generatePrivateKey)();
4093
+ const account = (0, import_accounts13.privateKeyToAccount)(privateKey);
3862
4094
  return {
3863
4095
  address: account.address,
3864
4096
  privateKey
@@ -3914,12 +4146,12 @@ function loadWallet() {
3914
4146
  function getOrCreateWallet() {
3915
4147
  const envKey = typeof process !== "undefined" && process.env ? process.env.BLOCKRUN_WALLET_KEY || process.env.BASE_CHAIN_WALLET_KEY : void 0;
3916
4148
  if (envKey) {
3917
- const account = (0, import_accounts12.privateKeyToAccount)(envKey);
4149
+ const account = (0, import_accounts13.privateKeyToAccount)(envKey);
3918
4150
  return { address: account.address, privateKey: envKey, isNew: false };
3919
4151
  }
3920
4152
  const fileKey = loadWallet();
3921
4153
  if (fileKey) {
3922
- const account = (0, import_accounts12.privateKeyToAccount)(fileKey);
4154
+ const account = (0, import_accounts13.privateKeyToAccount)(fileKey);
3923
4155
  return { address: account.address, privateKey: fileKey, isNew: false };
3924
4156
  }
3925
4157
  const { address, privateKey } = createWallet();
@@ -3929,11 +4161,11 @@ function getOrCreateWallet() {
3929
4161
  function getWalletAddress() {
3930
4162
  const envKey = typeof process !== "undefined" && process.env ? process.env.BLOCKRUN_WALLET_KEY || process.env.BASE_CHAIN_WALLET_KEY : void 0;
3931
4163
  if (envKey) {
3932
- return (0, import_accounts12.privateKeyToAccount)(envKey).address;
4164
+ return (0, import_accounts13.privateKeyToAccount)(envKey).address;
3933
4165
  }
3934
4166
  const fileKey = loadWallet();
3935
4167
  if (fileKey) {
3936
- return (0, import_accounts12.privateKeyToAccount)(fileKey).address;
4168
+ return (0, import_accounts13.privateKeyToAccount)(fileKey).address;
3937
4169
  }
3938
4170
  return null;
3939
4171
  }
@@ -4113,14 +4345,37 @@ async function getOrCreateSolanaWallet() {
4113
4345
  // src/solana-client.ts
4114
4346
  var SOLANA_API_URL = "https://sol.blockrun.ai/api";
4115
4347
  var DEFAULT_MAX_TOKENS2 = 1024;
4116
- var DEFAULT_TIMEOUT11 = 6e4;
4348
+ var DEFAULT_TIMEOUT12 = 6e4;
4117
4349
  var SDK_VERSION2 = "0.3.0";
4118
4350
  var USER_AGENT2 = `blockrun-ts/${SDK_VERSION2}`;
4351
+ var DEFAULT_SOLANA_RPC_URL = "https://sol.blockrun.ai/api/v1/solana/rpc";
4352
+ function resolveRpcConfig(rpcUrl, rpcHeaders) {
4353
+ const env = typeof process !== "undefined" && process.env ? process.env : {};
4354
+ const url = rpcUrl || env.SOLANA_RPC_URL || DEFAULT_SOLANA_RPC_URL;
4355
+ let headers;
4356
+ if (rpcHeaders) {
4357
+ headers = { ...rpcHeaders };
4358
+ } else if (env.SOLANA_RPC_HEADERS) {
4359
+ try {
4360
+ const parsed = JSON.parse(env.SOLANA_RPC_HEADERS);
4361
+ if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
4362
+ headers = Object.fromEntries(
4363
+ Object.entries(parsed).map(([k, v]) => [String(k), String(v)])
4364
+ );
4365
+ }
4366
+ } catch {
4367
+ }
4368
+ } else if (env.SOLANA_RPC_API_KEY) {
4369
+ headers = { "x-api-key": env.SOLANA_RPC_API_KEY };
4370
+ }
4371
+ return headers ? { url, headers } : { url };
4372
+ }
4119
4373
  var SolanaLLMClient = class {
4120
4374
  static SOLANA_API_URL = SOLANA_API_URL;
4121
4375
  privateKey;
4122
4376
  apiUrl;
4123
4377
  rpcUrl;
4378
+ rpcHeaders;
4124
4379
  timeout;
4125
4380
  sessionTotalUsd = 0;
4126
4381
  sessionCalls = 0;
@@ -4137,8 +4392,10 @@ var SolanaLLMClient = class {
4137
4392
  const apiUrl = options.apiUrl || SOLANA_API_URL;
4138
4393
  validateApiUrl(apiUrl);
4139
4394
  this.apiUrl = apiUrl.replace(/\/$/, "");
4140
- this.rpcUrl = options.rpcUrl || "https://api.mainnet-beta.solana.com";
4141
- this.timeout = options.timeout || DEFAULT_TIMEOUT11;
4395
+ const rpc = resolveRpcConfig(options.rpcUrl, options.rpcHeaders);
4396
+ this.rpcUrl = rpc.url;
4397
+ this.rpcHeaders = rpc.headers;
4398
+ this.timeout = options.timeout || DEFAULT_TIMEOUT12;
4142
4399
  }
4143
4400
  /** Get Solana wallet address (public key in base58). */
4144
4401
  async getWalletAddress() {
@@ -4196,7 +4453,7 @@ var SolanaLLMClient = class {
4196
4453
  try {
4197
4454
  const response = await fetch(this.rpcUrl, {
4198
4455
  method: "POST",
4199
- headers: { "Content-Type": "application/json" },
4456
+ headers: { "Content-Type": "application/json", ...this.rpcHeaders ?? {} },
4200
4457
  body: JSON.stringify({
4201
4458
  jsonrpc: "2.0",
4202
4459
  id: 1,
@@ -4447,7 +4704,8 @@ var SolanaLLMClient = class {
4447
4704
  maxTimeoutSeconds: details.maxTimeoutSeconds || 300,
4448
4705
  extra: details.extra,
4449
4706
  extensions,
4450
- rpcUrl: this.rpcUrl
4707
+ rpcUrl: this.rpcUrl,
4708
+ rpcHeaders: this.rpcHeaders
4451
4709
  }
4452
4710
  );
4453
4711
  const retryResponse = await this.fetchWithTimeout(url, {
@@ -4538,7 +4796,8 @@ var SolanaLLMClient = class {
4538
4796
  maxTimeoutSeconds: details.maxTimeoutSeconds || 300,
4539
4797
  extra: details.extra,
4540
4798
  extensions,
4541
- rpcUrl: this.rpcUrl
4799
+ rpcUrl: this.rpcUrl,
4800
+ rpcHeaders: this.rpcHeaders
4542
4801
  }
4543
4802
  );
4544
4803
  const retryResponse = await this.fetchWithTimeout(url, {
@@ -4629,7 +4888,8 @@ var SolanaLLMClient = class {
4629
4888
  maxTimeoutSeconds: details.maxTimeoutSeconds || 300,
4630
4889
  extra: details.extra,
4631
4890
  extensions,
4632
- rpcUrl: this.rpcUrl
4891
+ rpcUrl: this.rpcUrl,
4892
+ rpcHeaders: this.rpcHeaders
4633
4893
  }
4634
4894
  );
4635
4895
  const query = params ? "?" + new URLSearchParams(params).toString() : "";
@@ -5045,7 +5305,7 @@ var OpenAI = class {
5045
5305
  };
5046
5306
 
5047
5307
  // src/anthropic-compat.ts
5048
- var import_accounts13 = require("viem/accounts");
5308
+ var import_accounts14 = require("viem/accounts");
5049
5309
  var AnthropicClient = class {
5050
5310
  _client = null;
5051
5311
  _clientPromise = null;
@@ -5058,7 +5318,7 @@ var AnthropicClient = class {
5058
5318
  const key = options.privateKey ?? wallet.privateKey;
5059
5319
  validatePrivateKey(key);
5060
5320
  this._privateKey = key;
5061
- this._account = (0, import_accounts13.privateKeyToAccount)(this._privateKey);
5321
+ this._account = (0, import_accounts14.privateKeyToAccount)(this._privateKey);
5062
5322
  const apiUrl = options.apiUrl ?? "https://blockrun.ai/api";
5063
5323
  validateApiUrl(apiUrl);
5064
5324
  this._apiUrl = apiUrl.replace(/\/$/, "");
@@ -5164,7 +5424,9 @@ var AnthropicClient = class {
5164
5424
  LLMClient,
5165
5425
  MusicClient,
5166
5426
  OpenAI,
5427
+ PHONE_PRICES,
5167
5428
  PaymentError,
5429
+ PhoneClient,
5168
5430
  PriceClient,
5169
5431
  SOLANA_NETWORK,
5170
5432
  SOLANA_WALLET_FILE_PATH,