@blockrun/llm 2.4.0 → 2.5.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 +47 -0
- package/dist/index.cjs +391 -11
- package/dist/index.d.cts +141 -4
- package/dist/index.d.ts +141 -4
- package/dist/index.js +389 -10
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -3370,8 +3370,386 @@ var SurfClient = class {
|
|
|
3370
3370
|
}
|
|
3371
3371
|
};
|
|
3372
3372
|
|
|
3373
|
+
// 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;
|
|
3377
|
+
var DEFAULT_POLL_INTERVAL_MS = 5e3;
|
|
3378
|
+
var DEFAULT_POLL_BUDGET_MS = 3e5;
|
|
3379
|
+
var MAX_SIGNED_AUTH_SECONDS = 600;
|
|
3380
|
+
var BlockrunClient = class {
|
|
3381
|
+
account;
|
|
3382
|
+
privateKey;
|
|
3383
|
+
apiUrl;
|
|
3384
|
+
timeout;
|
|
3385
|
+
sessionTotalUsd = 0;
|
|
3386
|
+
sessionCalls = 0;
|
|
3387
|
+
constructor(options = {}) {
|
|
3388
|
+
const envKey = typeof process !== "undefined" && process.env ? process.env.BLOCKRUN_WALLET_KEY || process.env.BASE_CHAIN_WALLET_KEY : void 0;
|
|
3389
|
+
const privateKey = options.privateKey || envKey;
|
|
3390
|
+
if (!privateKey) {
|
|
3391
|
+
throw new Error(
|
|
3392
|
+
"Private key required. Pass privateKey in options or set BLOCKRUN_WALLET_KEY environment variable."
|
|
3393
|
+
);
|
|
3394
|
+
}
|
|
3395
|
+
validatePrivateKey(privateKey);
|
|
3396
|
+
this.privateKey = privateKey;
|
|
3397
|
+
this.account = privateKeyToAccount10(privateKey);
|
|
3398
|
+
const apiUrl = options.apiUrl || DEFAULT_API_URL10;
|
|
3399
|
+
validateApiUrl(apiUrl);
|
|
3400
|
+
this.apiUrl = apiUrl.replace(/\/$/, "");
|
|
3401
|
+
this.timeout = options.timeout || DEFAULT_TIMEOUT10;
|
|
3402
|
+
}
|
|
3403
|
+
/**
|
|
3404
|
+
* GET a BlockRun endpoint. `path` is everything after `/api` (a leading
|
|
3405
|
+
* `/api` is tolerated and stripped). Query params are URL-encoded; arrays
|
|
3406
|
+
* become repeated keys (`?a=1&a=2`); undefined/null are dropped.
|
|
3407
|
+
*/
|
|
3408
|
+
async get(path5, params) {
|
|
3409
|
+
const url = this.buildUrl(path5, params);
|
|
3410
|
+
return this.requestWithPayment(url, "GET");
|
|
3411
|
+
}
|
|
3412
|
+
/**
|
|
3413
|
+
* POST a BlockRun endpoint with a JSON body.
|
|
3414
|
+
*/
|
|
3415
|
+
async post(path5, body) {
|
|
3416
|
+
const url = this.buildUrl(path5);
|
|
3417
|
+
return this.requestWithPayment(url, "POST", body);
|
|
3418
|
+
}
|
|
3419
|
+
/**
|
|
3420
|
+
* Submit a long-running job and poll until it completes.
|
|
3421
|
+
*
|
|
3422
|
+
* Pattern: submit → 402 → sign → 202 `{ id, poll_url, status }` → loop GET
|
|
3423
|
+
* the poll_url with the SAME `PAYMENT-SIGNATURE` until status=completed (or
|
|
3424
|
+
* deadline exceeded). Settlement happens only when upstream returns 200 +
|
|
3425
|
+
* completed — upstream failure or caller giving up = no charge.
|
|
3426
|
+
*
|
|
3427
|
+
* If the gateway returns 200 directly on submit (no async surface), this
|
|
3428
|
+
* short-circuits and returns the body. Most long-running endpoints (image,
|
|
3429
|
+
* video, music, voice) return 202 with a poll_url.
|
|
3430
|
+
*/
|
|
3431
|
+
async poll(path5, body, options) {
|
|
3432
|
+
const submitUrl = this.buildUrl(path5);
|
|
3433
|
+
const budgetMs = options?.budgetMs ?? DEFAULT_POLL_BUDGET_MS;
|
|
3434
|
+
const intervalMs = options?.intervalMs ?? DEFAULT_POLL_INTERVAL_MS;
|
|
3435
|
+
const resp402 = await this.fetchWithTimeout(submitUrl, {
|
|
3436
|
+
method: "POST",
|
|
3437
|
+
headers: { "Content-Type": "application/json" },
|
|
3438
|
+
body: JSON.stringify(body ?? {})
|
|
3439
|
+
});
|
|
3440
|
+
if (resp402.status === 200) {
|
|
3441
|
+
return resp402.json();
|
|
3442
|
+
}
|
|
3443
|
+
if (resp402.status !== 402) {
|
|
3444
|
+
await this.throwApiError(resp402, `poll submit failed (${submitUrl})`);
|
|
3445
|
+
}
|
|
3446
|
+
const paymentPayload = await this.signFrom402(resp402, submitUrl, {
|
|
3447
|
+
description: "BlockRun async job",
|
|
3448
|
+
maxTimeoutSeconds: MAX_SIGNED_AUTH_SECONDS
|
|
3449
|
+
});
|
|
3450
|
+
const submitResp = await this.fetchWithTimeout(submitUrl, {
|
|
3451
|
+
method: "POST",
|
|
3452
|
+
headers: {
|
|
3453
|
+
"Content-Type": "application/json",
|
|
3454
|
+
"PAYMENT-SIGNATURE": paymentPayload
|
|
3455
|
+
},
|
|
3456
|
+
body: JSON.stringify(body ?? {})
|
|
3457
|
+
});
|
|
3458
|
+
if (submitResp.status === 402) {
|
|
3459
|
+
throw new PaymentError("Payment was rejected. Check your wallet balance.");
|
|
3460
|
+
}
|
|
3461
|
+
if (submitResp.status !== 200 && submitResp.status !== 202) {
|
|
3462
|
+
await this.throwApiError(submitResp, `poll submit failed (${submitUrl})`);
|
|
3463
|
+
}
|
|
3464
|
+
if (submitResp.status === 200) {
|
|
3465
|
+
this.recordSpending();
|
|
3466
|
+
return submitResp.json();
|
|
3467
|
+
}
|
|
3468
|
+
const submitData = await submitResp.json();
|
|
3469
|
+
if (!submitData.id || !submitData.poll_url) {
|
|
3470
|
+
throw new APIError(
|
|
3471
|
+
"Async submit response missing id/poll_url",
|
|
3472
|
+
submitResp.status,
|
|
3473
|
+
{ response: submitData }
|
|
3474
|
+
);
|
|
3475
|
+
}
|
|
3476
|
+
const pollUrl = this.absolute(submitData.poll_url);
|
|
3477
|
+
const deadline = Date.now() + budgetMs;
|
|
3478
|
+
let lastStatus = submitData.status || "queued";
|
|
3479
|
+
while (Date.now() < deadline) {
|
|
3480
|
+
await sleep(intervalMs);
|
|
3481
|
+
const pollResp = await this.fetchWithTimeout(pollUrl, {
|
|
3482
|
+
method: "GET",
|
|
3483
|
+
headers: { "PAYMENT-SIGNATURE": paymentPayload }
|
|
3484
|
+
});
|
|
3485
|
+
let pollData = {};
|
|
3486
|
+
try {
|
|
3487
|
+
pollData = await pollResp.json();
|
|
3488
|
+
} catch {
|
|
3489
|
+
}
|
|
3490
|
+
lastStatus = pollData.status || lastStatus;
|
|
3491
|
+
if (pollResp.status === 202 && (lastStatus === "queued" || lastStatus === "in_progress")) {
|
|
3492
|
+
continue;
|
|
3493
|
+
}
|
|
3494
|
+
if (lastStatus === "failed") {
|
|
3495
|
+
throw new APIError(
|
|
3496
|
+
`Upstream job failed: ${pollData.error || "unknown"}`,
|
|
3497
|
+
pollResp.status,
|
|
3498
|
+
sanitizeErrorResponse(pollData)
|
|
3499
|
+
);
|
|
3500
|
+
}
|
|
3501
|
+
if (pollResp.status === 200 && lastStatus === "completed") {
|
|
3502
|
+
this.recordSpending();
|
|
3503
|
+
return pollData;
|
|
3504
|
+
}
|
|
3505
|
+
if (pollResp.status !== 200 && pollResp.status !== 202 && pollResp.status !== 504) {
|
|
3506
|
+
await this.throwApiError(pollResp, `poll failed (${pollUrl})`);
|
|
3507
|
+
}
|
|
3508
|
+
}
|
|
3509
|
+
throw new APIError(
|
|
3510
|
+
`Job did not complete within ${Math.round(budgetMs / 1e3)}s (last status: ${lastStatus}). No payment was taken.`,
|
|
3511
|
+
504,
|
|
3512
|
+
{ id: submitData.id, last_status: lastStatus }
|
|
3513
|
+
);
|
|
3514
|
+
}
|
|
3515
|
+
/**
|
|
3516
|
+
* Stream a Server-Sent Events endpoint.
|
|
3517
|
+
*
|
|
3518
|
+
* Yields each `data: …` line parsed as JSON. Stops when the upstream emits
|
|
3519
|
+
* `data: [DONE]` or closes the connection. Caller is responsible for typing
|
|
3520
|
+
* the chunk shape; pass a generic for typed yields.
|
|
3521
|
+
*
|
|
3522
|
+
* Example — streaming chat:
|
|
3523
|
+
* for await (const chunk of br.stream<ChatChunk>("/v1/chat/completions", {
|
|
3524
|
+
* model: "anthropic/claude-sonnet-4-6",
|
|
3525
|
+
* messages: [{ role: "user", content: "Hi" }],
|
|
3526
|
+
* stream: true,
|
|
3527
|
+
* })) {
|
|
3528
|
+
* process.stdout.write(chunk.choices?.[0]?.delta?.content ?? "");
|
|
3529
|
+
* }
|
|
3530
|
+
*/
|
|
3531
|
+
async *stream(path5, body) {
|
|
3532
|
+
const url = this.buildUrl(path5);
|
|
3533
|
+
const requestBody = JSON.stringify(body ?? {});
|
|
3534
|
+
const resp402 = await this.fetchWithTimeout(url, {
|
|
3535
|
+
method: "POST",
|
|
3536
|
+
headers: { "Content-Type": "application/json" },
|
|
3537
|
+
body: requestBody
|
|
3538
|
+
});
|
|
3539
|
+
let streamResp;
|
|
3540
|
+
if (resp402.status === 200) {
|
|
3541
|
+
streamResp = resp402;
|
|
3542
|
+
} else if (resp402.status === 402) {
|
|
3543
|
+
const paymentPayload = await this.signFrom402(resp402, url, {
|
|
3544
|
+
description: "BlockRun stream"
|
|
3545
|
+
});
|
|
3546
|
+
streamResp = await this.fetchWithTimeout(url, {
|
|
3547
|
+
method: "POST",
|
|
3548
|
+
headers: {
|
|
3549
|
+
"Content-Type": "application/json",
|
|
3550
|
+
"PAYMENT-SIGNATURE": paymentPayload
|
|
3551
|
+
},
|
|
3552
|
+
body: requestBody
|
|
3553
|
+
});
|
|
3554
|
+
if (streamResp.status === 402) {
|
|
3555
|
+
throw new PaymentError(
|
|
3556
|
+
"Payment was rejected. Check your wallet balance."
|
|
3557
|
+
);
|
|
3558
|
+
}
|
|
3559
|
+
if (!streamResp.ok) {
|
|
3560
|
+
await this.throwApiError(streamResp, `stream failed after payment (${url})`);
|
|
3561
|
+
}
|
|
3562
|
+
this.recordSpending();
|
|
3563
|
+
} else {
|
|
3564
|
+
await this.throwApiError(resp402, `stream failed (${url})`);
|
|
3565
|
+
return;
|
|
3566
|
+
}
|
|
3567
|
+
if (!streamResp.body) {
|
|
3568
|
+
throw new APIError("Stream response has no body", streamResp.status, {});
|
|
3569
|
+
}
|
|
3570
|
+
const reader = streamResp.body.getReader();
|
|
3571
|
+
const decoder = new TextDecoder();
|
|
3572
|
+
let buffer = "";
|
|
3573
|
+
try {
|
|
3574
|
+
while (true) {
|
|
3575
|
+
const { done, value } = await reader.read();
|
|
3576
|
+
if (done) break;
|
|
3577
|
+
buffer += decoder.decode(value, { stream: true });
|
|
3578
|
+
const lines = buffer.split("\n");
|
|
3579
|
+
buffer = lines.pop() || "";
|
|
3580
|
+
for (const line of lines) {
|
|
3581
|
+
const trimmed = line.trim();
|
|
3582
|
+
if (!trimmed || !trimmed.startsWith("data: ")) continue;
|
|
3583
|
+
const data = trimmed.slice(6);
|
|
3584
|
+
if (data === "[DONE]") return;
|
|
3585
|
+
try {
|
|
3586
|
+
yield JSON.parse(data);
|
|
3587
|
+
} catch {
|
|
3588
|
+
}
|
|
3589
|
+
}
|
|
3590
|
+
}
|
|
3591
|
+
} finally {
|
|
3592
|
+
reader.releaseLock();
|
|
3593
|
+
}
|
|
3594
|
+
}
|
|
3595
|
+
// --------------------------------------------------------------------
|
|
3596
|
+
// Internal: shared infrastructure
|
|
3597
|
+
// --------------------------------------------------------------------
|
|
3598
|
+
buildUrl(path5, params) {
|
|
3599
|
+
let normalized = path5.startsWith("/") ? path5 : `/${path5}`;
|
|
3600
|
+
if (normalized.startsWith("/api/")) {
|
|
3601
|
+
normalized = normalized.slice(4);
|
|
3602
|
+
}
|
|
3603
|
+
const base = `${this.apiUrl}${normalized}`;
|
|
3604
|
+
if (!params) return base;
|
|
3605
|
+
const qs = new URLSearchParams();
|
|
3606
|
+
for (const [key, value] of Object.entries(params)) {
|
|
3607
|
+
if (value === void 0 || value === null) continue;
|
|
3608
|
+
if (Array.isArray(value)) {
|
|
3609
|
+
for (const v of value) {
|
|
3610
|
+
if (v === void 0 || v === null) continue;
|
|
3611
|
+
qs.append(key, String(v));
|
|
3612
|
+
}
|
|
3613
|
+
} else {
|
|
3614
|
+
qs.append(key, String(value));
|
|
3615
|
+
}
|
|
3616
|
+
}
|
|
3617
|
+
const query = qs.toString();
|
|
3618
|
+
return query ? `${base}?${query}` : base;
|
|
3619
|
+
}
|
|
3620
|
+
absolute(url) {
|
|
3621
|
+
if (url.startsWith("http://") || url.startsWith("https://")) return url;
|
|
3622
|
+
const base = this.apiUrl.endsWith("/api") ? this.apiUrl.slice(0, -"/api".length) : this.apiUrl;
|
|
3623
|
+
return `${base}${url}`;
|
|
3624
|
+
}
|
|
3625
|
+
async requestWithPayment(url, method, body) {
|
|
3626
|
+
const init = { method };
|
|
3627
|
+
if (method === "POST") {
|
|
3628
|
+
init.headers = { "Content-Type": "application/json" };
|
|
3629
|
+
init.body = JSON.stringify(body ?? {});
|
|
3630
|
+
}
|
|
3631
|
+
const response = await this.fetchWithTimeout(url, init);
|
|
3632
|
+
if (response.status === 402) {
|
|
3633
|
+
return this.handlePaymentAndRetry(url, method, body, response);
|
|
3634
|
+
}
|
|
3635
|
+
if (!response.ok) {
|
|
3636
|
+
await this.throwApiError(response, `${method} ${url} failed`);
|
|
3637
|
+
}
|
|
3638
|
+
return response.json();
|
|
3639
|
+
}
|
|
3640
|
+
async handlePaymentAndRetry(url, method, body, response) {
|
|
3641
|
+
const paymentPayload = await this.signFrom402(response, url, {
|
|
3642
|
+
description: "BlockRun"
|
|
3643
|
+
});
|
|
3644
|
+
const retryInit = {
|
|
3645
|
+
method,
|
|
3646
|
+
headers: { "PAYMENT-SIGNATURE": paymentPayload }
|
|
3647
|
+
};
|
|
3648
|
+
if (method === "POST") {
|
|
3649
|
+
retryInit.headers = {
|
|
3650
|
+
...retryInit.headers,
|
|
3651
|
+
"Content-Type": "application/json"
|
|
3652
|
+
};
|
|
3653
|
+
retryInit.body = JSON.stringify(body ?? {});
|
|
3654
|
+
}
|
|
3655
|
+
const retry = await this.fetchWithTimeout(url, retryInit);
|
|
3656
|
+
if (retry.status === 402) {
|
|
3657
|
+
throw new PaymentError(
|
|
3658
|
+
"Payment was rejected. Check your wallet balance."
|
|
3659
|
+
);
|
|
3660
|
+
}
|
|
3661
|
+
if (!retry.ok) {
|
|
3662
|
+
await this.throwApiError(retry, `${method} ${url} failed after payment`);
|
|
3663
|
+
}
|
|
3664
|
+
this.recordSpending();
|
|
3665
|
+
return retry.json();
|
|
3666
|
+
}
|
|
3667
|
+
/**
|
|
3668
|
+
* Read a 402 response's payment requirements (header or body), then sign and
|
|
3669
|
+
* return the base64 PAYMENT-SIGNATURE payload. Also records the cost-to-be
|
|
3670
|
+
* onto the response context (settled on `recordSpending`).
|
|
3671
|
+
*/
|
|
3672
|
+
async signFrom402(response, url, opts) {
|
|
3673
|
+
let paymentHeader = response.headers.get("payment-required");
|
|
3674
|
+
if (!paymentHeader) {
|
|
3675
|
+
try {
|
|
3676
|
+
const respBody = await response.json();
|
|
3677
|
+
if (respBody.x402Version !== void 0 || respBody.accepts !== void 0) {
|
|
3678
|
+
paymentHeader = btoa(JSON.stringify(respBody));
|
|
3679
|
+
}
|
|
3680
|
+
} catch {
|
|
3681
|
+
}
|
|
3682
|
+
}
|
|
3683
|
+
if (!paymentHeader) {
|
|
3684
|
+
throw new PaymentError("402 response but no payment requirements found");
|
|
3685
|
+
}
|
|
3686
|
+
const paymentRequired = parsePaymentRequired(paymentHeader);
|
|
3687
|
+
const details = extractPaymentDetails(paymentRequired);
|
|
3688
|
+
this.pendingCostUsd = parseFloat(details.amount) / 1e6;
|
|
3689
|
+
return createPaymentPayload(
|
|
3690
|
+
this.privateKey,
|
|
3691
|
+
this.account.address,
|
|
3692
|
+
details.recipient,
|
|
3693
|
+
details.amount,
|
|
3694
|
+
details.network || "eip155:8453",
|
|
3695
|
+
{
|
|
3696
|
+
resourceUrl: details.resource?.url || url,
|
|
3697
|
+
resourceDescription: details.resource?.description || opts.description,
|
|
3698
|
+
maxTimeoutSeconds: Math.max(
|
|
3699
|
+
details.maxTimeoutSeconds || 0,
|
|
3700
|
+
opts.maxTimeoutSeconds || 300
|
|
3701
|
+
),
|
|
3702
|
+
extra: details.extra
|
|
3703
|
+
}
|
|
3704
|
+
);
|
|
3705
|
+
}
|
|
3706
|
+
/** Accumulates the most-recent pending cost; settled by recordSpending. */
|
|
3707
|
+
pendingCostUsd = 0;
|
|
3708
|
+
recordSpending() {
|
|
3709
|
+
if (this.pendingCostUsd > 0) {
|
|
3710
|
+
this.sessionCalls += 1;
|
|
3711
|
+
this.sessionTotalUsd += this.pendingCostUsd;
|
|
3712
|
+
this.pendingCostUsd = 0;
|
|
3713
|
+
}
|
|
3714
|
+
}
|
|
3715
|
+
async throwApiError(resp, prefix) {
|
|
3716
|
+
let errorBody;
|
|
3717
|
+
try {
|
|
3718
|
+
errorBody = await resp.json();
|
|
3719
|
+
} catch {
|
|
3720
|
+
errorBody = { error: "Request failed" };
|
|
3721
|
+
}
|
|
3722
|
+
throw new APIError(
|
|
3723
|
+
`${prefix}: HTTP ${resp.status}`,
|
|
3724
|
+
resp.status,
|
|
3725
|
+
sanitizeErrorResponse(errorBody)
|
|
3726
|
+
);
|
|
3727
|
+
}
|
|
3728
|
+
async fetchWithTimeout(url, init) {
|
|
3729
|
+
const controller = new AbortController();
|
|
3730
|
+
const timeoutId = setTimeout(() => controller.abort(), this.timeout);
|
|
3731
|
+
try {
|
|
3732
|
+
return await fetch(url, { ...init, signal: controller.signal });
|
|
3733
|
+
} finally {
|
|
3734
|
+
clearTimeout(timeoutId);
|
|
3735
|
+
}
|
|
3736
|
+
}
|
|
3737
|
+
// --------------------------------------------------------------------
|
|
3738
|
+
// Public surface: wallet + spending
|
|
3739
|
+
// --------------------------------------------------------------------
|
|
3740
|
+
getWalletAddress() {
|
|
3741
|
+
return this.account.address;
|
|
3742
|
+
}
|
|
3743
|
+
getSpending() {
|
|
3744
|
+
return { totalUsd: this.sessionTotalUsd, calls: this.sessionCalls };
|
|
3745
|
+
}
|
|
3746
|
+
};
|
|
3747
|
+
function sleep(ms) {
|
|
3748
|
+
return new Promise((r) => setTimeout(r, ms));
|
|
3749
|
+
}
|
|
3750
|
+
|
|
3373
3751
|
// src/wallet.ts
|
|
3374
|
-
import { privateKeyToAccount as
|
|
3752
|
+
import { privateKeyToAccount as privateKeyToAccount11, generatePrivateKey } from "viem/accounts";
|
|
3375
3753
|
import * as fs2 from "fs";
|
|
3376
3754
|
import * as path2 from "path";
|
|
3377
3755
|
import * as os2 from "os";
|
|
@@ -3381,7 +3759,7 @@ var WALLET_DIR = path2.join(os2.homedir(), ".blockrun");
|
|
|
3381
3759
|
var WALLET_FILE = path2.join(WALLET_DIR, ".session");
|
|
3382
3760
|
function createWallet() {
|
|
3383
3761
|
const privateKey = generatePrivateKey();
|
|
3384
|
-
const account =
|
|
3762
|
+
const account = privateKeyToAccount11(privateKey);
|
|
3385
3763
|
return {
|
|
3386
3764
|
address: account.address,
|
|
3387
3765
|
privateKey
|
|
@@ -3437,12 +3815,12 @@ function loadWallet() {
|
|
|
3437
3815
|
function getOrCreateWallet() {
|
|
3438
3816
|
const envKey = typeof process !== "undefined" && process.env ? process.env.BLOCKRUN_WALLET_KEY || process.env.BASE_CHAIN_WALLET_KEY : void 0;
|
|
3439
3817
|
if (envKey) {
|
|
3440
|
-
const account =
|
|
3818
|
+
const account = privateKeyToAccount11(envKey);
|
|
3441
3819
|
return { address: account.address, privateKey: envKey, isNew: false };
|
|
3442
3820
|
}
|
|
3443
3821
|
const fileKey = loadWallet();
|
|
3444
3822
|
if (fileKey) {
|
|
3445
|
-
const account =
|
|
3823
|
+
const account = privateKeyToAccount11(fileKey);
|
|
3446
3824
|
return { address: account.address, privateKey: fileKey, isNew: false };
|
|
3447
3825
|
}
|
|
3448
3826
|
const { address, privateKey } = createWallet();
|
|
@@ -3452,11 +3830,11 @@ function getOrCreateWallet() {
|
|
|
3452
3830
|
function getWalletAddress() {
|
|
3453
3831
|
const envKey = typeof process !== "undefined" && process.env ? process.env.BLOCKRUN_WALLET_KEY || process.env.BASE_CHAIN_WALLET_KEY : void 0;
|
|
3454
3832
|
if (envKey) {
|
|
3455
|
-
return
|
|
3833
|
+
return privateKeyToAccount11(envKey).address;
|
|
3456
3834
|
}
|
|
3457
3835
|
const fileKey = loadWallet();
|
|
3458
3836
|
if (fileKey) {
|
|
3459
|
-
return
|
|
3837
|
+
return privateKeyToAccount11(fileKey).address;
|
|
3460
3838
|
}
|
|
3461
3839
|
return null;
|
|
3462
3840
|
}
|
|
@@ -3636,7 +4014,7 @@ async function getOrCreateSolanaWallet() {
|
|
|
3636
4014
|
// src/solana-client.ts
|
|
3637
4015
|
var SOLANA_API_URL = "https://sol.blockrun.ai/api";
|
|
3638
4016
|
var DEFAULT_MAX_TOKENS2 = 1024;
|
|
3639
|
-
var
|
|
4017
|
+
var DEFAULT_TIMEOUT11 = 6e4;
|
|
3640
4018
|
var SDK_VERSION2 = "0.3.0";
|
|
3641
4019
|
var USER_AGENT2 = `blockrun-ts/${SDK_VERSION2}`;
|
|
3642
4020
|
var SolanaLLMClient = class {
|
|
@@ -3661,7 +4039,7 @@ var SolanaLLMClient = class {
|
|
|
3661
4039
|
validateApiUrl(apiUrl);
|
|
3662
4040
|
this.apiUrl = apiUrl.replace(/\/$/, "");
|
|
3663
4041
|
this.rpcUrl = options.rpcUrl || "https://api.mainnet-beta.solana.com";
|
|
3664
|
-
this.timeout = options.timeout ||
|
|
4042
|
+
this.timeout = options.timeout || DEFAULT_TIMEOUT11;
|
|
3665
4043
|
}
|
|
3666
4044
|
/** Get Solana wallet address (public key in base58). */
|
|
3667
4045
|
async getWalletAddress() {
|
|
@@ -4568,7 +4946,7 @@ var OpenAI = class {
|
|
|
4568
4946
|
};
|
|
4569
4947
|
|
|
4570
4948
|
// src/anthropic-compat.ts
|
|
4571
|
-
import { privateKeyToAccount as
|
|
4949
|
+
import { privateKeyToAccount as privateKeyToAccount12 } from "viem/accounts";
|
|
4572
4950
|
var AnthropicClient = class {
|
|
4573
4951
|
_client = null;
|
|
4574
4952
|
_clientPromise = null;
|
|
@@ -4581,7 +4959,7 @@ var AnthropicClient = class {
|
|
|
4581
4959
|
const key = options.privateKey ?? wallet.privateKey;
|
|
4582
4960
|
validatePrivateKey(key);
|
|
4583
4961
|
this._privateKey = key;
|
|
4584
|
-
this._account =
|
|
4962
|
+
this._account = privateKeyToAccount12(this._privateKey);
|
|
4585
4963
|
const apiUrl = options.apiUrl ?? "https://blockrun.ai/api";
|
|
4586
4964
|
validateApiUrl(apiUrl);
|
|
4587
4965
|
this._apiUrl = apiUrl.replace(/\/$/, "");
|
|
@@ -4679,6 +5057,7 @@ export {
|
|
|
4679
5057
|
APIError,
|
|
4680
5058
|
AnthropicClient,
|
|
4681
5059
|
BASE_CHAIN_ID,
|
|
5060
|
+
BlockrunClient,
|
|
4682
5061
|
BlockrunError,
|
|
4683
5062
|
ImageClient,
|
|
4684
5063
|
KNOWN_PROVIDERS,
|