@blockrun/franklin 3.14.0 → 3.15.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/agent/context.js +14 -5
- package/dist/tools/index.js +2 -0
- package/dist/tools/zerox-base.js +6 -62
- package/package.json +1 -1
package/dist/agent/context.js
CHANGED
|
@@ -213,11 +213,20 @@ You run on the BlockRun AI Gateway. When the user asks you to "test the BlockRun
|
|
|
213
213
|
- Use the **\`JupiterQuote\` and \`JupiterSwap\` built-in tools** — they call Jupiter's Ultra API directly from this process. The user is the first-party caller of Jupiter; we are not a gateway proxy here. A 20 bps platform fee is collected on-chain as part of the swap (Jupiter Referral Program — official integrator mechanism, not a hidden cost).
|
|
214
214
|
- Do NOT try to call \`/v1/jupiter/...\` on the BlockRun gateway — there is no such endpoint (Jupiter ToU forbids the gateway-proxy model).
|
|
215
215
|
|
|
216
|
-
**Base DEX swap (0x V2
|
|
217
|
-
|
|
218
|
-
-
|
|
219
|
-
-
|
|
220
|
-
-
|
|
216
|
+
**Base DEX swap (0x V2 via BlockRun gateway)** — three modes, pick by user's wallet state:
|
|
217
|
+
|
|
218
|
+
- **\`Base0xQuote\`** (read-only): inspect price + impact + route. Free.
|
|
219
|
+
- **\`Base0xSwap\`** (Permit2): user signs Permit2 typed-data + submits the tx themselves to Base RPC. **User needs ETH for gas.** Routes through BlockRun gateway \`/v1/zerox/{price,quote}\` — no 0x signup needed.
|
|
220
|
+
- **\`Base0xGaslessSwap\`** (Gasless V2): user signs ONLY EIP-712 typed-data (offline, no on-chain action). 0x's relayer broadcasts the trade and pays gas. **User does NOT need any ETH.** Only works for Permit-supporting input tokens (USDC, DAI). USDT etc. do not support Permit on Base — the tool errors with that instruction. Routes through \`/v1/zerox/gasless/*\`.
|
|
221
|
+
|
|
222
|
+
**Pick the right tool:**
|
|
223
|
+
- User holds ETH on Base → use \`Base0xSwap\` (more flexibility, supports any input token).
|
|
224
|
+
- User holds USDC/DAI but no ETH → use \`Base0xGaslessSwap\` (zero gas needed).
|
|
225
|
+
- User asks for a quote without committing → use \`Base0xQuote\`.
|
|
226
|
+
|
|
227
|
+
Symbol shortcuts pre-mapped on all three: ETH (native, Base0xSwap only), WETH, USDC, USDT, CBBTC, CBETH, AERO, DAI. Raw \`0x...\` addresses pass through.
|
|
228
|
+
|
|
229
|
+
On-chain affiliate (20 bps in sell-token, force-set server-side) flows to BlockRun treasury at settlement on all three paths. BlockRun never custodies user keys; signing is always local.
|
|
221
230
|
|
|
222
231
|
**Sandbox (POST, x402-paid)**
|
|
223
232
|
- \`/v1/modal/{...path}\` — Modal GPU sandbox passthrough (create/exec/etc.).
|
package/dist/tools/index.js
CHANGED
|
@@ -27,6 +27,7 @@ import { webhookPostCapability } from './webhook.js';
|
|
|
27
27
|
import { walletCapability } from './wallet.js';
|
|
28
28
|
import { jupiterQuoteCapability, jupiterSwapCapability } from './jupiter.js';
|
|
29
29
|
import { base0xQuoteCapability, base0xSwapCapability } from './zerox-base.js';
|
|
30
|
+
import { base0xGaslessSwapCapability } from './zerox-gasless.js';
|
|
30
31
|
import { defiLlamaProtocolsCapability, defiLlamaProtocolCapability, defiLlamaChainsCapability, defiLlamaYieldsCapability, defiLlamaPriceCapability, } from './defillama.js';
|
|
31
32
|
import { createTradingCapabilities } from './trading-execute.js';
|
|
32
33
|
import { Portfolio } from '../trading/portfolio.js';
|
|
@@ -151,6 +152,7 @@ export const allCapabilities = [
|
|
|
151
152
|
jupiterSwapCapability,
|
|
152
153
|
base0xQuoteCapability,
|
|
153
154
|
base0xSwapCapability,
|
|
155
|
+
base0xGaslessSwapCapability,
|
|
154
156
|
defiLlamaProtocolsCapability,
|
|
155
157
|
defiLlamaProtocolCapability,
|
|
156
158
|
defiLlamaChainsCapability,
|
package/dist/tools/zerox-base.js
CHANGED
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
import { createWalletClient, http, publicActions, concat, numberToHex, size, parseUnits, formatUnits, maxUint256, erc20Abi, getContract, } from 'viem';
|
|
25
25
|
import { privateKeyToAccount } from 'viem/accounts';
|
|
26
26
|
import { base } from 'viem/chains';
|
|
27
|
-
import { getOrCreateWallet
|
|
27
|
+
import { getOrCreateWallet } from '@blockrun/llm';
|
|
28
28
|
import { loadConfig } from '../commands/config.js';
|
|
29
29
|
import { loadChain, API_URLS, VERSION } from '../config.js';
|
|
30
30
|
// ─── BlockRun affiliate identity on Base ─────────────────────────────────
|
|
@@ -146,8 +146,8 @@ function makeClient(account) {
|
|
|
146
146
|
transport: http(resolveBaseRpcUrl()),
|
|
147
147
|
}).extend(publicActions);
|
|
148
148
|
}
|
|
149
|
-
// ─── 0x calls via BlockRun gateway (
|
|
150
|
-
async function
|
|
149
|
+
// ─── 0x calls via BlockRun gateway (free public passthrough) ─────────────
|
|
150
|
+
async function gatewayGet(path, params, ctx) {
|
|
151
151
|
const chain = loadChain();
|
|
152
152
|
const apiUrl = API_URLS[chain];
|
|
153
153
|
const endpoint = `${apiUrl}${ZEROX_GATEWAY_PATH}/${path}?${params.toString()}`;
|
|
@@ -160,22 +160,11 @@ async function gatewayGetWithPayment(path, params, ctx) {
|
|
|
160
160
|
const onAbort = () => controller.abort();
|
|
161
161
|
ctx.abortSignal.addEventListener('abort', onAbort, { once: true });
|
|
162
162
|
try {
|
|
163
|
-
|
|
163
|
+
const response = await fetch(endpoint, {
|
|
164
164
|
method: 'GET',
|
|
165
165
|
headers,
|
|
166
166
|
signal: controller.signal,
|
|
167
167
|
});
|
|
168
|
-
if (response.status === 402) {
|
|
169
|
-
const paymentHeaders = await signGatewayPayment(response, chain, endpoint);
|
|
170
|
-
if (!paymentHeaders) {
|
|
171
|
-
throw new Error('Payment signing failed — check wallet balance');
|
|
172
|
-
}
|
|
173
|
-
response = await fetch(endpoint, {
|
|
174
|
-
method: 'GET',
|
|
175
|
-
headers: { ...headers, ...paymentHeaders },
|
|
176
|
-
signal: controller.signal,
|
|
177
|
-
});
|
|
178
|
-
}
|
|
179
168
|
if (!response.ok) {
|
|
180
169
|
const text = await response.text().catch(() => '');
|
|
181
170
|
throw new Error(`BlockRun gateway /v1/zerox/${path} returned ${response.status}: ${text.slice(0, 300)}`);
|
|
@@ -187,51 +176,6 @@ async function gatewayGetWithPayment(path, params, ctx) {
|
|
|
187
176
|
ctx.abortSignal.removeEventListener('abort', onAbort);
|
|
188
177
|
}
|
|
189
178
|
}
|
|
190
|
-
async function signGatewayPayment(response, chain, endpoint) {
|
|
191
|
-
try {
|
|
192
|
-
let header = response.headers.get('payment-required');
|
|
193
|
-
if (!header) {
|
|
194
|
-
try {
|
|
195
|
-
const body = (await response.json());
|
|
196
|
-
if (body.x402 || body.accepts)
|
|
197
|
-
header = btoa(JSON.stringify(body));
|
|
198
|
-
}
|
|
199
|
-
catch {
|
|
200
|
-
/* ignore */
|
|
201
|
-
}
|
|
202
|
-
}
|
|
203
|
-
if (!header)
|
|
204
|
-
return null;
|
|
205
|
-
if (chain === 'solana') {
|
|
206
|
-
const wallet = await getOrCreateSolanaWallet();
|
|
207
|
-
const paymentRequired = parsePaymentRequired(header);
|
|
208
|
-
const details = extractPaymentDetails(paymentRequired, SOLANA_NETWORK);
|
|
209
|
-
const secretBytes = await solanaKeyToBytes(wallet.privateKey);
|
|
210
|
-
const feePayer = details.extra?.feePayer || details.recipient;
|
|
211
|
-
const payload = await createSolanaPaymentPayload(secretBytes, wallet.address, details.recipient, details.amount, feePayer, {
|
|
212
|
-
resourceUrl: details.resource?.url || endpoint,
|
|
213
|
-
resourceDescription: details.resource?.description || 'Franklin 0x swap call',
|
|
214
|
-
maxTimeoutSeconds: details.maxTimeoutSeconds || 60,
|
|
215
|
-
extra: details.extra,
|
|
216
|
-
});
|
|
217
|
-
return { 'PAYMENT-SIGNATURE': payload };
|
|
218
|
-
}
|
|
219
|
-
const wallet = await getOrCreateWallet();
|
|
220
|
-
const paymentRequired = parsePaymentRequired(header);
|
|
221
|
-
const details = extractPaymentDetails(paymentRequired);
|
|
222
|
-
const payload = await createPaymentPayload(wallet.privateKey, wallet.address, details.recipient, details.amount, details.network || 'eip155:8453', {
|
|
223
|
-
resourceUrl: details.resource?.url || endpoint,
|
|
224
|
-
resourceDescription: details.resource?.description || 'Franklin 0x swap call',
|
|
225
|
-
maxTimeoutSeconds: details.maxTimeoutSeconds || 60,
|
|
226
|
-
extra: details.extra,
|
|
227
|
-
});
|
|
228
|
-
return { 'PAYMENT-SIGNATURE': payload };
|
|
229
|
-
}
|
|
230
|
-
catch (err) {
|
|
231
|
-
console.error(`[franklin] 0x gateway payment error: ${err.message}`);
|
|
232
|
-
return null;
|
|
233
|
-
}
|
|
234
|
-
}
|
|
235
179
|
function buildSwapParams(args) {
|
|
236
180
|
// Affiliate params (swapFeeRecipient/Bps/Token) are NOT set here —
|
|
237
181
|
// the BlockRun gateway forces them server-side, ensuring every
|
|
@@ -294,7 +238,7 @@ async function executeBase0xQuote(input, ctx) {
|
|
|
294
238
|
taker: walletAddress,
|
|
295
239
|
});
|
|
296
240
|
try {
|
|
297
|
-
const price = await
|
|
241
|
+
const price = await gatewayGet('price', params, ctx);
|
|
298
242
|
if (!price.liquidityAvailable && price.liquidityAvailable !== undefined) {
|
|
299
243
|
return {
|
|
300
244
|
output: `0x reports no liquidity for ${symbolFor(sellTokenAddr)} → ${symbolFor(buyTokenAddr)} on Base.`,
|
|
@@ -342,7 +286,7 @@ async function executeBase0xSwap(input, ctx) {
|
|
|
342
286
|
// Gateway forces affiliate params server-side; user pays $0.001 USDC.
|
|
343
287
|
let quote;
|
|
344
288
|
try {
|
|
345
|
-
quote = await
|
|
289
|
+
quote = await gatewayGet('quote', params, ctx);
|
|
346
290
|
}
|
|
347
291
|
catch (err) {
|
|
348
292
|
return {
|
package/package.json
CHANGED