@blockrun/llm 0.1.1
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/LICENSE +21 -0
- package/README.md +320 -0
- package/dist/chunk-FCKQTBEP.mjs +90 -0
- package/dist/chunk-HEBXNMVQ.mjs +48 -0
- package/dist/chunk-R7MQBF5Y.mjs +26586 -0
- package/dist/chunk-TYQEUMVI.mjs +206 -0
- package/dist/esm-3BUZROFC.mjs +7964 -0
- package/dist/index.d.mts +295 -0
- package/dist/index.d.ts +295 -0
- package/dist/index.esm-FLTVMT4C.mjs +157 -0
- package/dist/index.js +36968 -0
- package/dist/index.mjs +428 -0
- package/dist/validation-FPOEEOR4.mjs +15 -0
- package/dist/x402-ELHVFRUU.mjs +27 -0
- package/package.json +65 -0
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
// src/x402.ts
|
|
2
|
+
import { signTypedData } from "viem/accounts";
|
|
3
|
+
var BASE_CHAIN_ID = 8453;
|
|
4
|
+
var USDC_BASE = "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913";
|
|
5
|
+
var SOLANA_NETWORK = "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp";
|
|
6
|
+
var USDC_SOLANA = "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v";
|
|
7
|
+
var SOLANA_USDC_DECIMALS = 6;
|
|
8
|
+
var DEFAULT_COMPUTE_UNIT_PRICE_MICROLAMPORTS = 1;
|
|
9
|
+
var DEFAULT_COMPUTE_UNIT_LIMIT = 8e3;
|
|
10
|
+
var USDC_DOMAIN = {
|
|
11
|
+
name: "USD Coin",
|
|
12
|
+
version: "2",
|
|
13
|
+
chainId: BASE_CHAIN_ID,
|
|
14
|
+
verifyingContract: USDC_BASE
|
|
15
|
+
};
|
|
16
|
+
var TRANSFER_TYPES = {
|
|
17
|
+
TransferWithAuthorization: [
|
|
18
|
+
{ name: "from", type: "address" },
|
|
19
|
+
{ name: "to", type: "address" },
|
|
20
|
+
{ name: "value", type: "uint256" },
|
|
21
|
+
{ name: "validAfter", type: "uint256" },
|
|
22
|
+
{ name: "validBefore", type: "uint256" },
|
|
23
|
+
{ name: "nonce", type: "bytes32" }
|
|
24
|
+
]
|
|
25
|
+
};
|
|
26
|
+
function createNonce() {
|
|
27
|
+
const bytes = new Uint8Array(32);
|
|
28
|
+
crypto.getRandomValues(bytes);
|
|
29
|
+
return `0x${Array.from(bytes).map((b) => b.toString(16).padStart(2, "0")).join("")}`;
|
|
30
|
+
}
|
|
31
|
+
async function createPaymentPayload(privateKey, fromAddress, recipient, amount, network = "eip155:8453", options = {}) {
|
|
32
|
+
const now = Math.floor(Date.now() / 1e3);
|
|
33
|
+
const validAfter = now - 600;
|
|
34
|
+
const validBefore = now + (options.maxTimeoutSeconds || 300);
|
|
35
|
+
const nonce = createNonce();
|
|
36
|
+
const domain = USDC_DOMAIN;
|
|
37
|
+
const signature = await signTypedData({
|
|
38
|
+
privateKey,
|
|
39
|
+
domain,
|
|
40
|
+
types: TRANSFER_TYPES,
|
|
41
|
+
primaryType: "TransferWithAuthorization",
|
|
42
|
+
message: {
|
|
43
|
+
from: fromAddress,
|
|
44
|
+
to: recipient,
|
|
45
|
+
value: BigInt(amount),
|
|
46
|
+
validAfter: BigInt(validAfter),
|
|
47
|
+
validBefore: BigInt(validBefore),
|
|
48
|
+
nonce
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
const paymentData = {
|
|
52
|
+
x402Version: 2,
|
|
53
|
+
resource: {
|
|
54
|
+
url: options.resourceUrl || "https://blockrun.ai/api/v1/chat/completions",
|
|
55
|
+
description: options.resourceDescription || "BlockRun AI API call",
|
|
56
|
+
mimeType: "application/json"
|
|
57
|
+
},
|
|
58
|
+
accepted: {
|
|
59
|
+
scheme: "exact",
|
|
60
|
+
network,
|
|
61
|
+
amount,
|
|
62
|
+
asset: USDC_BASE,
|
|
63
|
+
payTo: recipient,
|
|
64
|
+
maxTimeoutSeconds: options.maxTimeoutSeconds || 300,
|
|
65
|
+
extra: { name: "USD Coin", version: "2" }
|
|
66
|
+
},
|
|
67
|
+
payload: {
|
|
68
|
+
signature,
|
|
69
|
+
authorization: {
|
|
70
|
+
from: fromAddress,
|
|
71
|
+
to: recipient,
|
|
72
|
+
value: amount,
|
|
73
|
+
validAfter: validAfter.toString(),
|
|
74
|
+
validBefore: validBefore.toString(),
|
|
75
|
+
nonce
|
|
76
|
+
}
|
|
77
|
+
},
|
|
78
|
+
extensions: options.extensions || {}
|
|
79
|
+
};
|
|
80
|
+
return btoa(JSON.stringify(paymentData));
|
|
81
|
+
}
|
|
82
|
+
async function createSolanaPaymentPayload(secretKey, fromAddress, recipient, amount, feePayer, options = {}) {
|
|
83
|
+
const { Connection, PublicKey, TransactionMessage, VersionedTransaction, ComputeBudgetProgram } = await import("./index.esm-FLTVMT4C.mjs");
|
|
84
|
+
const { getAssociatedTokenAddress, createTransferCheckedInstruction, getMint } = await import("./esm-3BUZROFC.mjs");
|
|
85
|
+
const { Keypair } = await import("./index.esm-FLTVMT4C.mjs");
|
|
86
|
+
const rpcUrl = options.rpcUrl || "https://api.mainnet-beta.solana.com";
|
|
87
|
+
const connection = new Connection(rpcUrl);
|
|
88
|
+
const keypair = Keypair.fromSecretKey(secretKey);
|
|
89
|
+
const feePayerPubkey = new PublicKey(feePayer);
|
|
90
|
+
const ownerPubkey = keypair.publicKey;
|
|
91
|
+
const tokenMint = new PublicKey(USDC_SOLANA);
|
|
92
|
+
const payToPubkey = new PublicKey(recipient);
|
|
93
|
+
const mintInfo = await getMint(connection, tokenMint);
|
|
94
|
+
const sourceATA = await getAssociatedTokenAddress(tokenMint, ownerPubkey, false);
|
|
95
|
+
const destinationATA = await getAssociatedTokenAddress(tokenMint, payToPubkey, false);
|
|
96
|
+
const { blockhash } = await connection.getLatestBlockhash();
|
|
97
|
+
const setComputeUnitPriceIx = ComputeBudgetProgram.setComputeUnitPrice({
|
|
98
|
+
microLamports: DEFAULT_COMPUTE_UNIT_PRICE_MICROLAMPORTS
|
|
99
|
+
});
|
|
100
|
+
const setComputeUnitLimitIx = ComputeBudgetProgram.setComputeUnitLimit({
|
|
101
|
+
units: DEFAULT_COMPUTE_UNIT_LIMIT
|
|
102
|
+
});
|
|
103
|
+
const transferIx = createTransferCheckedInstruction(
|
|
104
|
+
sourceATA,
|
|
105
|
+
tokenMint,
|
|
106
|
+
destinationATA,
|
|
107
|
+
ownerPubkey,
|
|
108
|
+
BigInt(amount),
|
|
109
|
+
mintInfo.decimals
|
|
110
|
+
);
|
|
111
|
+
const messageV0 = new TransactionMessage({
|
|
112
|
+
payerKey: feePayerPubkey,
|
|
113
|
+
recentBlockhash: blockhash,
|
|
114
|
+
instructions: [setComputeUnitLimitIx, setComputeUnitPriceIx, transferIx]
|
|
115
|
+
}).compileToV0Message();
|
|
116
|
+
const transaction = new VersionedTransaction(messageV0);
|
|
117
|
+
transaction.sign([keypair]);
|
|
118
|
+
const serializedTx = Buffer.from(transaction.serialize()).toString("base64");
|
|
119
|
+
const paymentData = {
|
|
120
|
+
x402Version: 2,
|
|
121
|
+
resource: {
|
|
122
|
+
url: options.resourceUrl || "https://blockrun.ai/api/v1/chat/completions",
|
|
123
|
+
description: options.resourceDescription || "BlockRun AI API call",
|
|
124
|
+
mimeType: "application/json"
|
|
125
|
+
},
|
|
126
|
+
accepted: {
|
|
127
|
+
scheme: "exact",
|
|
128
|
+
network: SOLANA_NETWORK,
|
|
129
|
+
amount,
|
|
130
|
+
asset: USDC_SOLANA,
|
|
131
|
+
payTo: recipient,
|
|
132
|
+
maxTimeoutSeconds: options.maxTimeoutSeconds || 300,
|
|
133
|
+
extra: options.extra || { feePayer }
|
|
134
|
+
},
|
|
135
|
+
payload: {
|
|
136
|
+
transaction: serializedTx
|
|
137
|
+
},
|
|
138
|
+
extensions: options.extensions || {}
|
|
139
|
+
};
|
|
140
|
+
return btoa(JSON.stringify(paymentData));
|
|
141
|
+
}
|
|
142
|
+
function parsePaymentRequired(headerValue) {
|
|
143
|
+
try {
|
|
144
|
+
const decoded = atob(headerValue);
|
|
145
|
+
const parsed = JSON.parse(decoded);
|
|
146
|
+
if (!parsed.accepts || !Array.isArray(parsed.accepts)) {
|
|
147
|
+
throw new Error("Invalid payment required structure: missing or invalid 'accepts' field");
|
|
148
|
+
}
|
|
149
|
+
return parsed;
|
|
150
|
+
} catch (error) {
|
|
151
|
+
if (error instanceof Error) {
|
|
152
|
+
if (error.message.includes("Invalid payment required structure")) {
|
|
153
|
+
throw error;
|
|
154
|
+
}
|
|
155
|
+
throw new Error("Failed to parse payment required header: invalid format");
|
|
156
|
+
}
|
|
157
|
+
throw new Error("Failed to parse payment required header");
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
function extractPaymentDetails(paymentRequired, preferredNetwork) {
|
|
161
|
+
const accepts = paymentRequired.accepts || [];
|
|
162
|
+
if (accepts.length === 0) {
|
|
163
|
+
throw new Error("No payment options in payment required response");
|
|
164
|
+
}
|
|
165
|
+
let option = null;
|
|
166
|
+
if (preferredNetwork) {
|
|
167
|
+
option = accepts.find((opt) => opt.network === preferredNetwork) || null;
|
|
168
|
+
}
|
|
169
|
+
if (!option) {
|
|
170
|
+
option = accepts[0];
|
|
171
|
+
}
|
|
172
|
+
const amount = option.amount || option.maxAmountRequired;
|
|
173
|
+
if (!amount) {
|
|
174
|
+
throw new Error("No amount found in payment requirements");
|
|
175
|
+
}
|
|
176
|
+
return {
|
|
177
|
+
amount,
|
|
178
|
+
recipient: option.payTo,
|
|
179
|
+
network: option.network,
|
|
180
|
+
asset: option.asset,
|
|
181
|
+
scheme: option.scheme,
|
|
182
|
+
maxTimeoutSeconds: option.maxTimeoutSeconds || 300,
|
|
183
|
+
extra: option.extra,
|
|
184
|
+
resource: paymentRequired.resource
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
function isSolanaNetwork(network) {
|
|
188
|
+
return network.startsWith("solana:");
|
|
189
|
+
}
|
|
190
|
+
function getAvailableNetworks(paymentRequired) {
|
|
191
|
+
return paymentRequired.accepts.map((opt) => opt.network).filter((network) => Boolean(network));
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
export {
|
|
195
|
+
BASE_CHAIN_ID,
|
|
196
|
+
USDC_BASE,
|
|
197
|
+
SOLANA_NETWORK,
|
|
198
|
+
USDC_SOLANA,
|
|
199
|
+
SOLANA_USDC_DECIMALS,
|
|
200
|
+
createPaymentPayload,
|
|
201
|
+
createSolanaPaymentPayload,
|
|
202
|
+
parsePaymentRequired,
|
|
203
|
+
extractPaymentDetails,
|
|
204
|
+
isSolanaNetwork,
|
|
205
|
+
getAvailableNetworks
|
|
206
|
+
};
|