@blockrun/llm 2.5.0 → 2.8.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/README.md +31 -2
- package/dist/index.cjs +464 -44
- package/dist/index.d.cts +329 -7
- package/dist/index.d.ts +329 -7
- package/dist/index.js +459 -43
- package/package.json +1 -1
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://
|
|
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/
|
|
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
|
|
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,357 @@ 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/portrait.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 PORTRAIT_ENROLLMENT_PRICE_USD = 0.01;
|
|
2906
|
+
var PortraitClient = class {
|
|
2907
|
+
account;
|
|
2908
|
+
privateKey;
|
|
2909
|
+
apiUrl;
|
|
2910
|
+
timeout;
|
|
2911
|
+
sessionTotalUsd = 0;
|
|
2912
|
+
sessionCalls = 0;
|
|
2913
|
+
constructor(options = {}) {
|
|
2914
|
+
const envKey = typeof process !== "undefined" && process.env ? process.env.BLOCKRUN_WALLET_KEY || process.env.BASE_CHAIN_WALLET_KEY : void 0;
|
|
2915
|
+
const privateKey = options.privateKey || envKey;
|
|
2916
|
+
if (!privateKey) {
|
|
2917
|
+
throw new Error(
|
|
2918
|
+
"Private key required. Pass privateKey in options or set BLOCKRUN_WALLET_KEY environment variable."
|
|
2919
|
+
);
|
|
2920
|
+
}
|
|
2921
|
+
validatePrivateKey(privateKey);
|
|
2922
|
+
this.privateKey = privateKey;
|
|
2923
|
+
this.account = privateKeyToAccount7(privateKey);
|
|
2924
|
+
const apiUrl = options.apiUrl || DEFAULT_API_URL7;
|
|
2925
|
+
validateApiUrl(apiUrl);
|
|
2926
|
+
this.apiUrl = apiUrl.replace(/\/$/, "");
|
|
2927
|
+
this.timeout = options.timeout || DEFAULT_TIMEOUT7;
|
|
2928
|
+
}
|
|
2929
|
+
/** EVM wallet address used for payments. */
|
|
2930
|
+
getWalletAddress() {
|
|
2931
|
+
return this.account.address;
|
|
2932
|
+
}
|
|
2933
|
+
/** Session-cumulative USD spend + call count across this client instance. */
|
|
2934
|
+
getSpending() {
|
|
2935
|
+
return { totalUsd: this.sessionTotalUsd, calls: this.sessionCalls };
|
|
2936
|
+
}
|
|
2937
|
+
/**
|
|
2938
|
+
* Enroll a Virtual Portrait from a face image URL. $0.01 (promo).
|
|
2939
|
+
*
|
|
2940
|
+
* Payment is settled only after Token360 confirms the enrollment, so failed
|
|
2941
|
+
* enrollments never charge your wallet.
|
|
2942
|
+
*
|
|
2943
|
+
* @param options.name Display name (1–64 chars).
|
|
2944
|
+
* @param options.imageUrl Public HTTPS URL to a JPG/PNG/WEBP image (≤10 MB).
|
|
2945
|
+
* @returns The enrollment record, including `asset_id` (`ta_xxxxxx`).
|
|
2946
|
+
*/
|
|
2947
|
+
async enroll(options) {
|
|
2948
|
+
const name = typeof options?.name === "string" ? options.name.trim() : "";
|
|
2949
|
+
if (name.length < 1 || name.length > 64) {
|
|
2950
|
+
throw new Error("name is required and must be 1\u201364 characters");
|
|
2951
|
+
}
|
|
2952
|
+
const imageUrl = typeof options?.imageUrl === "string" ? options.imageUrl.trim() : "";
|
|
2953
|
+
if (!/^https?:\/\//i.test(imageUrl)) {
|
|
2954
|
+
throw new Error(
|
|
2955
|
+
"imageUrl must be a public http(s) URL to a JPG/PNG/WEBP image"
|
|
2956
|
+
);
|
|
2957
|
+
}
|
|
2958
|
+
const data = await this.request({
|
|
2959
|
+
name,
|
|
2960
|
+
image_url: imageUrl
|
|
2961
|
+
});
|
|
2962
|
+
return data;
|
|
2963
|
+
}
|
|
2964
|
+
// ─── Internals ─────────────────────────────────────────────────────────
|
|
2965
|
+
async request(body) {
|
|
2966
|
+
const url = `${this.apiUrl}/v1/portrait/enroll`;
|
|
2967
|
+
const response = await this.fetchWithTimeout(url, {
|
|
2968
|
+
method: "POST",
|
|
2969
|
+
headers: { "Content-Type": "application/json" },
|
|
2970
|
+
body: JSON.stringify(body)
|
|
2971
|
+
});
|
|
2972
|
+
if (response.status === 402) {
|
|
2973
|
+
return this.handlePaymentAndRetry(url, body, response);
|
|
2974
|
+
}
|
|
2975
|
+
return this.unwrap(response, false);
|
|
2976
|
+
}
|
|
2977
|
+
async handlePaymentAndRetry(url, body, response) {
|
|
2978
|
+
let paymentHeader = response.headers.get("payment-required");
|
|
2979
|
+
if (!paymentHeader) {
|
|
2980
|
+
try {
|
|
2981
|
+
const rb = await response.json();
|
|
2982
|
+
if (rb.x402 || rb.accepts) paymentHeader = btoa(JSON.stringify(rb));
|
|
2983
|
+
} catch {
|
|
2984
|
+
}
|
|
2985
|
+
}
|
|
2986
|
+
if (!paymentHeader) {
|
|
2987
|
+
throw new PaymentError("402 response but no payment requirements found");
|
|
2988
|
+
}
|
|
2989
|
+
const paymentRequired = parsePaymentRequired(paymentHeader);
|
|
2990
|
+
const details = extractPaymentDetails(paymentRequired);
|
|
2991
|
+
const paymentPayload = await createPaymentPayload(
|
|
2992
|
+
this.privateKey,
|
|
2993
|
+
this.account.address,
|
|
2994
|
+
details.recipient,
|
|
2995
|
+
details.amount,
|
|
2996
|
+
details.network || "eip155:8453",
|
|
2997
|
+
{
|
|
2998
|
+
resourceUrl: details.resource?.url || url,
|
|
2999
|
+
resourceDescription: details.resource?.description || "BlockRun Virtual Portrait",
|
|
3000
|
+
maxTimeoutSeconds: details.maxTimeoutSeconds || 300,
|
|
3001
|
+
extra: details.extra
|
|
3002
|
+
}
|
|
3003
|
+
);
|
|
3004
|
+
const retry = await this.fetchWithTimeout(url, {
|
|
3005
|
+
method: "POST",
|
|
3006
|
+
headers: {
|
|
3007
|
+
"Content-Type": "application/json",
|
|
3008
|
+
"PAYMENT-SIGNATURE": paymentPayload
|
|
3009
|
+
},
|
|
3010
|
+
body: JSON.stringify(body)
|
|
3011
|
+
});
|
|
3012
|
+
if (retry.status === 402) {
|
|
3013
|
+
throw new PaymentError("Payment was rejected. Check your wallet balance.");
|
|
3014
|
+
}
|
|
3015
|
+
const data = await this.unwrap(retry, true);
|
|
3016
|
+
const costUsd = Number.parseFloat(details.amount) / 1e6;
|
|
3017
|
+
this.sessionCalls += 1;
|
|
3018
|
+
this.sessionTotalUsd += costUsd;
|
|
3019
|
+
if (data && typeof data === "object" && !("txHash" in data)) {
|
|
3020
|
+
const settlement = data.settlement;
|
|
3021
|
+
if (settlement?.tx_hash) {
|
|
3022
|
+
data.txHash = settlement.tx_hash;
|
|
3023
|
+
}
|
|
3024
|
+
}
|
|
3025
|
+
return data;
|
|
3026
|
+
}
|
|
3027
|
+
async unwrap(response, afterPayment) {
|
|
3028
|
+
if (response.ok) {
|
|
3029
|
+
return response.json();
|
|
3030
|
+
}
|
|
3031
|
+
let errorBody;
|
|
3032
|
+
try {
|
|
3033
|
+
errorBody = await response.json();
|
|
3034
|
+
} catch {
|
|
3035
|
+
errorBody = { error: "Request failed" };
|
|
3036
|
+
}
|
|
3037
|
+
const prefix = afterPayment ? "API error after payment" : "API error";
|
|
3038
|
+
throw new APIError(
|
|
3039
|
+
`${prefix}: ${response.status}`,
|
|
3040
|
+
response.status,
|
|
3041
|
+
sanitizeErrorResponse(errorBody)
|
|
3042
|
+
);
|
|
3043
|
+
}
|
|
3044
|
+
async fetchWithTimeout(url, init) {
|
|
3045
|
+
const controller = new AbortController();
|
|
3046
|
+
const timeoutId = setTimeout(() => controller.abort(), this.timeout);
|
|
3047
|
+
try {
|
|
3048
|
+
return await fetch(url, { ...init, signal: controller.signal });
|
|
3049
|
+
} finally {
|
|
3050
|
+
clearTimeout(timeoutId);
|
|
3051
|
+
}
|
|
3052
|
+
}
|
|
3053
|
+
};
|
|
3054
|
+
|
|
3055
|
+
// src/search.ts
|
|
3056
|
+
import { privateKeyToAccount as privateKeyToAccount8 } from "viem/accounts";
|
|
3057
|
+
var DEFAULT_API_URL8 = "https://blockrun.ai/api";
|
|
3058
|
+
var DEFAULT_TIMEOUT8 = 6e4;
|
|
3059
|
+
var SearchClient = class {
|
|
3060
|
+
account;
|
|
3061
|
+
privateKey;
|
|
3062
|
+
apiUrl;
|
|
3063
|
+
timeout;
|
|
3064
|
+
constructor(options = {}) {
|
|
3065
|
+
const envKey = typeof process !== "undefined" && process.env ? process.env.BLOCKRUN_WALLET_KEY || process.env.BASE_CHAIN_WALLET_KEY : void 0;
|
|
3066
|
+
const privateKey = options.privateKey || envKey;
|
|
3067
|
+
if (!privateKey) {
|
|
3068
|
+
throw new Error(
|
|
3069
|
+
"Private key required. Pass privateKey in options or set BLOCKRUN_WALLET_KEY environment variable."
|
|
3070
|
+
);
|
|
3071
|
+
}
|
|
3072
|
+
validatePrivateKey(privateKey);
|
|
3073
|
+
this.privateKey = privateKey;
|
|
3074
|
+
this.account = privateKeyToAccount8(privateKey);
|
|
3075
|
+
const apiUrl = options.apiUrl || DEFAULT_API_URL8;
|
|
3076
|
+
validateApiUrl(apiUrl);
|
|
3077
|
+
this.apiUrl = apiUrl.replace(/\/$/, "");
|
|
3078
|
+
this.timeout = options.timeout || DEFAULT_TIMEOUT8;
|
|
3079
|
+
}
|
|
2696
3080
|
async search(query, options) {
|
|
2697
3081
|
if (!query || query.length > 1e3) {
|
|
2698
3082
|
throw new Error("query must be 1-1000 characters");
|
|
@@ -2805,9 +3189,9 @@ var SearchClient = class {
|
|
|
2805
3189
|
};
|
|
2806
3190
|
|
|
2807
3191
|
// src/x-client.ts
|
|
2808
|
-
import { privateKeyToAccount as
|
|
2809
|
-
var
|
|
2810
|
-
var
|
|
3192
|
+
import { privateKeyToAccount as privateKeyToAccount9 } from "viem/accounts";
|
|
3193
|
+
var DEFAULT_API_URL9 = "https://blockrun.ai/api";
|
|
3194
|
+
var DEFAULT_TIMEOUT9 = 6e4;
|
|
2811
3195
|
var XClient = class _XClient {
|
|
2812
3196
|
account;
|
|
2813
3197
|
privateKey;
|
|
@@ -2830,11 +3214,11 @@ var XClient = class _XClient {
|
|
|
2830
3214
|
}
|
|
2831
3215
|
validatePrivateKey(privateKey);
|
|
2832
3216
|
this.privateKey = privateKey;
|
|
2833
|
-
this.account =
|
|
2834
|
-
const apiUrl = options.apiUrl ||
|
|
3217
|
+
this.account = privateKeyToAccount9(privateKey);
|
|
3218
|
+
const apiUrl = options.apiUrl || DEFAULT_API_URL9;
|
|
2835
3219
|
validateApiUrl(apiUrl);
|
|
2836
3220
|
this.apiUrl = apiUrl.replace(/\/$/, "");
|
|
2837
|
-
this.timeout = options.timeout ||
|
|
3221
|
+
this.timeout = options.timeout || DEFAULT_TIMEOUT9;
|
|
2838
3222
|
}
|
|
2839
3223
|
// ───────── User endpoints ─────────
|
|
2840
3224
|
userLookup(usernames) {
|
|
@@ -3012,9 +3396,9 @@ var XClient = class _XClient {
|
|
|
3012
3396
|
};
|
|
3013
3397
|
|
|
3014
3398
|
// src/price.ts
|
|
3015
|
-
import { privateKeyToAccount as
|
|
3016
|
-
var
|
|
3017
|
-
var
|
|
3399
|
+
import { privateKeyToAccount as privateKeyToAccount10 } from "viem/accounts";
|
|
3400
|
+
var DEFAULT_API_URL10 = "https://blockrun.ai/api";
|
|
3401
|
+
var DEFAULT_TIMEOUT10 = 3e4;
|
|
3018
3402
|
var PriceClient = class {
|
|
3019
3403
|
account = null;
|
|
3020
3404
|
privateKey = null;
|
|
@@ -3032,12 +3416,12 @@ var PriceClient = class {
|
|
|
3032
3416
|
if (privateKey) {
|
|
3033
3417
|
validatePrivateKey(privateKey);
|
|
3034
3418
|
this.privateKey = privateKey;
|
|
3035
|
-
this.account =
|
|
3419
|
+
this.account = privateKeyToAccount10(privateKey);
|
|
3036
3420
|
}
|
|
3037
|
-
const apiUrl = options.apiUrl ||
|
|
3421
|
+
const apiUrl = options.apiUrl || DEFAULT_API_URL10;
|
|
3038
3422
|
validateApiUrl(apiUrl);
|
|
3039
3423
|
this.apiUrl = apiUrl.replace(/\/$/, "");
|
|
3040
|
-
this.timeout = options.timeout ||
|
|
3424
|
+
this.timeout = options.timeout || DEFAULT_TIMEOUT10;
|
|
3041
3425
|
}
|
|
3042
3426
|
async price(category, symbol, options) {
|
|
3043
3427
|
if (!symbol) throw new Error("symbol is required");
|
|
@@ -3216,9 +3600,9 @@ function buildUrl(base, query) {
|
|
|
3216
3600
|
}
|
|
3217
3601
|
|
|
3218
3602
|
// src/surf.ts
|
|
3219
|
-
import { privateKeyToAccount as
|
|
3220
|
-
var
|
|
3221
|
-
var
|
|
3603
|
+
import { privateKeyToAccount as privateKeyToAccount11 } from "viem/accounts";
|
|
3604
|
+
var DEFAULT_API_URL11 = "https://blockrun.ai/api";
|
|
3605
|
+
var DEFAULT_TIMEOUT11 = 6e4;
|
|
3222
3606
|
var SURF_PREFIX = "/v1/surf";
|
|
3223
3607
|
var SurfClient = class {
|
|
3224
3608
|
account;
|
|
@@ -3235,11 +3619,11 @@ var SurfClient = class {
|
|
|
3235
3619
|
}
|
|
3236
3620
|
validatePrivateKey(privateKey);
|
|
3237
3621
|
this.privateKey = privateKey;
|
|
3238
|
-
this.account =
|
|
3239
|
-
const apiUrl = options.apiUrl ||
|
|
3622
|
+
this.account = privateKeyToAccount11(privateKey);
|
|
3623
|
+
const apiUrl = options.apiUrl || DEFAULT_API_URL11;
|
|
3240
3624
|
validateApiUrl(apiUrl);
|
|
3241
3625
|
this.apiUrl = apiUrl.replace(/\/$/, "");
|
|
3242
|
-
this.timeout = options.timeout ||
|
|
3626
|
+
this.timeout = options.timeout || DEFAULT_TIMEOUT11;
|
|
3243
3627
|
}
|
|
3244
3628
|
/**
|
|
3245
3629
|
* GET a Surf endpoint. `path` is everything after `/v1/surf` (a leading
|
|
@@ -3371,9 +3755,9 @@ var SurfClient = class {
|
|
|
3371
3755
|
};
|
|
3372
3756
|
|
|
3373
3757
|
// src/blockrun.ts
|
|
3374
|
-
import { privateKeyToAccount as
|
|
3375
|
-
var
|
|
3376
|
-
var
|
|
3758
|
+
import { privateKeyToAccount as privateKeyToAccount12 } from "viem/accounts";
|
|
3759
|
+
var DEFAULT_API_URL12 = "https://blockrun.ai/api";
|
|
3760
|
+
var DEFAULT_TIMEOUT12 = 6e4;
|
|
3377
3761
|
var DEFAULT_POLL_INTERVAL_MS = 5e3;
|
|
3378
3762
|
var DEFAULT_POLL_BUDGET_MS = 3e5;
|
|
3379
3763
|
var MAX_SIGNED_AUTH_SECONDS = 600;
|
|
@@ -3394,11 +3778,11 @@ var BlockrunClient = class {
|
|
|
3394
3778
|
}
|
|
3395
3779
|
validatePrivateKey(privateKey);
|
|
3396
3780
|
this.privateKey = privateKey;
|
|
3397
|
-
this.account =
|
|
3398
|
-
const apiUrl = options.apiUrl ||
|
|
3781
|
+
this.account = privateKeyToAccount12(privateKey);
|
|
3782
|
+
const apiUrl = options.apiUrl || DEFAULT_API_URL12;
|
|
3399
3783
|
validateApiUrl(apiUrl);
|
|
3400
3784
|
this.apiUrl = apiUrl.replace(/\/$/, "");
|
|
3401
|
-
this.timeout = options.timeout ||
|
|
3785
|
+
this.timeout = options.timeout || DEFAULT_TIMEOUT12;
|
|
3402
3786
|
}
|
|
3403
3787
|
/**
|
|
3404
3788
|
* GET a BlockRun endpoint. `path` is everything after `/api` (a leading
|
|
@@ -3749,7 +4133,7 @@ function sleep(ms) {
|
|
|
3749
4133
|
}
|
|
3750
4134
|
|
|
3751
4135
|
// src/wallet.ts
|
|
3752
|
-
import { privateKeyToAccount as
|
|
4136
|
+
import { privateKeyToAccount as privateKeyToAccount13, generatePrivateKey } from "viem/accounts";
|
|
3753
4137
|
import * as fs2 from "fs";
|
|
3754
4138
|
import * as path2 from "path";
|
|
3755
4139
|
import * as os2 from "os";
|
|
@@ -3759,7 +4143,7 @@ var WALLET_DIR = path2.join(os2.homedir(), ".blockrun");
|
|
|
3759
4143
|
var WALLET_FILE = path2.join(WALLET_DIR, ".session");
|
|
3760
4144
|
function createWallet() {
|
|
3761
4145
|
const privateKey = generatePrivateKey();
|
|
3762
|
-
const account =
|
|
4146
|
+
const account = privateKeyToAccount13(privateKey);
|
|
3763
4147
|
return {
|
|
3764
4148
|
address: account.address,
|
|
3765
4149
|
privateKey
|
|
@@ -3815,12 +4199,12 @@ function loadWallet() {
|
|
|
3815
4199
|
function getOrCreateWallet() {
|
|
3816
4200
|
const envKey = typeof process !== "undefined" && process.env ? process.env.BLOCKRUN_WALLET_KEY || process.env.BASE_CHAIN_WALLET_KEY : void 0;
|
|
3817
4201
|
if (envKey) {
|
|
3818
|
-
const account =
|
|
4202
|
+
const account = privateKeyToAccount13(envKey);
|
|
3819
4203
|
return { address: account.address, privateKey: envKey, isNew: false };
|
|
3820
4204
|
}
|
|
3821
4205
|
const fileKey = loadWallet();
|
|
3822
4206
|
if (fileKey) {
|
|
3823
|
-
const account =
|
|
4207
|
+
const account = privateKeyToAccount13(fileKey);
|
|
3824
4208
|
return { address: account.address, privateKey: fileKey, isNew: false };
|
|
3825
4209
|
}
|
|
3826
4210
|
const { address, privateKey } = createWallet();
|
|
@@ -3830,11 +4214,11 @@ function getOrCreateWallet() {
|
|
|
3830
4214
|
function getWalletAddress() {
|
|
3831
4215
|
const envKey = typeof process !== "undefined" && process.env ? process.env.BLOCKRUN_WALLET_KEY || process.env.BASE_CHAIN_WALLET_KEY : void 0;
|
|
3832
4216
|
if (envKey) {
|
|
3833
|
-
return
|
|
4217
|
+
return privateKeyToAccount13(envKey).address;
|
|
3834
4218
|
}
|
|
3835
4219
|
const fileKey = loadWallet();
|
|
3836
4220
|
if (fileKey) {
|
|
3837
|
-
return
|
|
4221
|
+
return privateKeyToAccount13(fileKey).address;
|
|
3838
4222
|
}
|
|
3839
4223
|
return null;
|
|
3840
4224
|
}
|
|
@@ -4014,14 +4398,37 @@ async function getOrCreateSolanaWallet() {
|
|
|
4014
4398
|
// src/solana-client.ts
|
|
4015
4399
|
var SOLANA_API_URL = "https://sol.blockrun.ai/api";
|
|
4016
4400
|
var DEFAULT_MAX_TOKENS2 = 1024;
|
|
4017
|
-
var
|
|
4401
|
+
var DEFAULT_TIMEOUT13 = 6e4;
|
|
4018
4402
|
var SDK_VERSION2 = "0.3.0";
|
|
4019
4403
|
var USER_AGENT2 = `blockrun-ts/${SDK_VERSION2}`;
|
|
4404
|
+
var DEFAULT_SOLANA_RPC_URL = "https://sol.blockrun.ai/api/v1/solana/rpc";
|
|
4405
|
+
function resolveRpcConfig(rpcUrl, rpcHeaders) {
|
|
4406
|
+
const env = typeof process !== "undefined" && process.env ? process.env : {};
|
|
4407
|
+
const url = rpcUrl || env.SOLANA_RPC_URL || DEFAULT_SOLANA_RPC_URL;
|
|
4408
|
+
let headers;
|
|
4409
|
+
if (rpcHeaders) {
|
|
4410
|
+
headers = { ...rpcHeaders };
|
|
4411
|
+
} else if (env.SOLANA_RPC_HEADERS) {
|
|
4412
|
+
try {
|
|
4413
|
+
const parsed = JSON.parse(env.SOLANA_RPC_HEADERS);
|
|
4414
|
+
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
|
|
4415
|
+
headers = Object.fromEntries(
|
|
4416
|
+
Object.entries(parsed).map(([k, v]) => [String(k), String(v)])
|
|
4417
|
+
);
|
|
4418
|
+
}
|
|
4419
|
+
} catch {
|
|
4420
|
+
}
|
|
4421
|
+
} else if (env.SOLANA_RPC_API_KEY) {
|
|
4422
|
+
headers = { "x-api-key": env.SOLANA_RPC_API_KEY };
|
|
4423
|
+
}
|
|
4424
|
+
return headers ? { url, headers } : { url };
|
|
4425
|
+
}
|
|
4020
4426
|
var SolanaLLMClient = class {
|
|
4021
4427
|
static SOLANA_API_URL = SOLANA_API_URL;
|
|
4022
4428
|
privateKey;
|
|
4023
4429
|
apiUrl;
|
|
4024
4430
|
rpcUrl;
|
|
4431
|
+
rpcHeaders;
|
|
4025
4432
|
timeout;
|
|
4026
4433
|
sessionTotalUsd = 0;
|
|
4027
4434
|
sessionCalls = 0;
|
|
@@ -4038,8 +4445,10 @@ var SolanaLLMClient = class {
|
|
|
4038
4445
|
const apiUrl = options.apiUrl || SOLANA_API_URL;
|
|
4039
4446
|
validateApiUrl(apiUrl);
|
|
4040
4447
|
this.apiUrl = apiUrl.replace(/\/$/, "");
|
|
4041
|
-
|
|
4042
|
-
this.
|
|
4448
|
+
const rpc = resolveRpcConfig(options.rpcUrl, options.rpcHeaders);
|
|
4449
|
+
this.rpcUrl = rpc.url;
|
|
4450
|
+
this.rpcHeaders = rpc.headers;
|
|
4451
|
+
this.timeout = options.timeout || DEFAULT_TIMEOUT13;
|
|
4043
4452
|
}
|
|
4044
4453
|
/** Get Solana wallet address (public key in base58). */
|
|
4045
4454
|
async getWalletAddress() {
|
|
@@ -4097,7 +4506,7 @@ var SolanaLLMClient = class {
|
|
|
4097
4506
|
try {
|
|
4098
4507
|
const response = await fetch(this.rpcUrl, {
|
|
4099
4508
|
method: "POST",
|
|
4100
|
-
headers: { "Content-Type": "application/json" },
|
|
4509
|
+
headers: { "Content-Type": "application/json", ...this.rpcHeaders ?? {} },
|
|
4101
4510
|
body: JSON.stringify({
|
|
4102
4511
|
jsonrpc: "2.0",
|
|
4103
4512
|
id: 1,
|
|
@@ -4348,7 +4757,8 @@ var SolanaLLMClient = class {
|
|
|
4348
4757
|
maxTimeoutSeconds: details.maxTimeoutSeconds || 300,
|
|
4349
4758
|
extra: details.extra,
|
|
4350
4759
|
extensions,
|
|
4351
|
-
rpcUrl: this.rpcUrl
|
|
4760
|
+
rpcUrl: this.rpcUrl,
|
|
4761
|
+
rpcHeaders: this.rpcHeaders
|
|
4352
4762
|
}
|
|
4353
4763
|
);
|
|
4354
4764
|
const retryResponse = await this.fetchWithTimeout(url, {
|
|
@@ -4439,7 +4849,8 @@ var SolanaLLMClient = class {
|
|
|
4439
4849
|
maxTimeoutSeconds: details.maxTimeoutSeconds || 300,
|
|
4440
4850
|
extra: details.extra,
|
|
4441
4851
|
extensions,
|
|
4442
|
-
rpcUrl: this.rpcUrl
|
|
4852
|
+
rpcUrl: this.rpcUrl,
|
|
4853
|
+
rpcHeaders: this.rpcHeaders
|
|
4443
4854
|
}
|
|
4444
4855
|
);
|
|
4445
4856
|
const retryResponse = await this.fetchWithTimeout(url, {
|
|
@@ -4530,7 +4941,8 @@ var SolanaLLMClient = class {
|
|
|
4530
4941
|
maxTimeoutSeconds: details.maxTimeoutSeconds || 300,
|
|
4531
4942
|
extra: details.extra,
|
|
4532
4943
|
extensions,
|
|
4533
|
-
rpcUrl: this.rpcUrl
|
|
4944
|
+
rpcUrl: this.rpcUrl,
|
|
4945
|
+
rpcHeaders: this.rpcHeaders
|
|
4534
4946
|
}
|
|
4535
4947
|
);
|
|
4536
4948
|
const query = params ? "?" + new URLSearchParams(params).toString() : "";
|
|
@@ -4946,7 +5358,7 @@ var OpenAI = class {
|
|
|
4946
5358
|
};
|
|
4947
5359
|
|
|
4948
5360
|
// src/anthropic-compat.ts
|
|
4949
|
-
import { privateKeyToAccount as
|
|
5361
|
+
import { privateKeyToAccount as privateKeyToAccount14 } from "viem/accounts";
|
|
4950
5362
|
var AnthropicClient = class {
|
|
4951
5363
|
_client = null;
|
|
4952
5364
|
_clientPromise = null;
|
|
@@ -4959,7 +5371,7 @@ var AnthropicClient = class {
|
|
|
4959
5371
|
const key = options.privateKey ?? wallet.privateKey;
|
|
4960
5372
|
validatePrivateKey(key);
|
|
4961
5373
|
this._privateKey = key;
|
|
4962
|
-
this._account =
|
|
5374
|
+
this._account = privateKeyToAccount14(this._privateKey);
|
|
4963
5375
|
const apiUrl = options.apiUrl ?? "https://blockrun.ai/api";
|
|
4964
5376
|
validateApiUrl(apiUrl);
|
|
4965
5377
|
this._apiUrl = apiUrl.replace(/\/$/, "");
|
|
@@ -5064,7 +5476,11 @@ export {
|
|
|
5064
5476
|
LLMClient,
|
|
5065
5477
|
MusicClient,
|
|
5066
5478
|
OpenAI,
|
|
5479
|
+
PHONE_PRICES,
|
|
5480
|
+
PORTRAIT_ENROLLMENT_PRICE_USD,
|
|
5067
5481
|
PaymentError,
|
|
5482
|
+
PhoneClient,
|
|
5483
|
+
PortraitClient,
|
|
5068
5484
|
PriceClient,
|
|
5069
5485
|
SOLANA_NETWORK,
|
|
5070
5486
|
SOLANA_WALLET_FILE as SOLANA_WALLET_FILE_PATH,
|