@barzkit/sdk 0.1.2 → 0.1.4
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/CHANGELOG.md +36 -0
- package/README.md +4 -4
- package/dist/index.cjs +435 -20
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +113 -1
- package/dist/index.d.ts +113 -1
- package/dist/index.js +421 -22
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,40 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [0.1.4] - 2026-03-01
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
|
|
12
|
+
- x402 payment protocol support: machine-to-machine HTTP 402 payments
|
|
13
|
+
- `enableX402()` method on `BarzAgent` — configure payment limits and domain whitelist
|
|
14
|
+
- `fetchWithPayment()` method on `BarzAgent` — auto-pay 402 responses and retry with proof
|
|
15
|
+
- `X402Config` and `X402PaymentRequest` interfaces
|
|
16
|
+
- `X402Manager` — per-request and daily spend limit enforcement with 24h rolling window
|
|
17
|
+
- `parsePaymentRequired()` — parse 402 response headers into structured payment request
|
|
18
|
+
- `validateDomain()` — domain whitelist check for payment endpoints
|
|
19
|
+
- `buildPaymentTransaction()` — build ERC-20 transfer for x402 payment
|
|
20
|
+
- `X402Error` error class
|
|
21
|
+
- Unit tests for x402 parsing, validation, manager, and fetch flow
|
|
22
|
+
|
|
23
|
+
## [0.1.3] - 2026-03-01
|
|
24
|
+
|
|
25
|
+
### Added
|
|
26
|
+
|
|
27
|
+
- `swap()` method on `BarzAgent` — swap tokens via Uniswap V3 (Sepolia)
|
|
28
|
+
- `lend()` method on `BarzAgent` — supply tokens to Aave V3 (Sepolia)
|
|
29
|
+
- `SwapParams` and `LendParams` interfaces
|
|
30
|
+
- `src/actions/tokens.ts` — `resolveToken()`, `getTokenDecimals()`, `isNativeETH()`, `ETH_SENTINEL`
|
|
31
|
+
- `src/actions/swap.ts` — `buildSwapTransactions()`, `getSwapTokenAddresses()`, `UNISWAP_V3_ROUTER`
|
|
32
|
+
- `src/actions/lend.ts` — `buildLendTransactions()`, `getLendTokenAddresses()`, `AAVE_V3_POOL`
|
|
33
|
+
- Token permission validation for DeFi actions (`allowedTokens` check)
|
|
34
|
+
- Unit tests for tokens, swap, and lend calldata builders
|
|
35
|
+
- `defi-agent` example
|
|
36
|
+
- DeFi actions guide (`docs/guides/defi-actions.md`)
|
|
37
|
+
|
|
38
|
+
### Changed
|
|
39
|
+
|
|
40
|
+
- Extracted `executeBatch()` helper in `account.ts` (reused by `batchTransactions`, `swap`, `lend`)
|
|
41
|
+
|
|
8
42
|
## [0.1.2] - 2026-03-01
|
|
9
43
|
|
|
10
44
|
### Added
|
|
@@ -67,6 +101,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
67
101
|
- `AgentEvent` type definitions for future event hooks
|
|
68
102
|
- Dual-package build: ESM (`.mjs`) + CJS (`.js`) + DTS (`.d.ts`)
|
|
69
103
|
|
|
104
|
+
[0.1.4]: https://github.com/barzkit/sdk/compare/v0.1.3...v0.1.4
|
|
105
|
+
[0.1.3]: https://github.com/barzkit/sdk/compare/v0.1.2...v0.1.3
|
|
70
106
|
[0.1.2]: https://github.com/barzkit/sdk/compare/v0.1.1...v0.1.2
|
|
71
107
|
[0.1.1]: https://github.com/barzkit/sdk/compare/v0.1.0...v0.1.1
|
|
72
108
|
[0.1.0]: https://github.com/barzkit/sdk/releases/tag/v0.1.0
|
package/README.md
CHANGED
|
@@ -156,11 +156,11 @@ See [examples](https://github.com/barzkit/examples) for complete working example
|
|
|
156
156
|
|
|
157
157
|
- [x] Core SDK: createWallet, sendTransaction, permissions, freeze
|
|
158
158
|
- [x] Batch transactions: atomic multi-call in one UserOperation
|
|
159
|
-
- [
|
|
160
|
-
- [
|
|
159
|
+
- [x] Multi-chain: Base Sepolia, Base mainnet
|
|
160
|
+
- [x] DeFi actions: swap, lend (Uniswap, Aave)
|
|
161
|
+
- [x] x402 payment handler
|
|
161
162
|
- [ ] ElizaOS plugin
|
|
162
163
|
- [ ] LangChain tool
|
|
163
|
-
- [ ] x402 payment handler
|
|
164
164
|
- [ ] On-chain permission enforcement via Diamond Facets
|
|
165
165
|
|
|
166
166
|
## Contributing
|
|
@@ -173,4 +173,4 @@ MIT
|
|
|
173
173
|
|
|
174
174
|
---
|
|
175
175
|
|
|
176
|
-
[Documentation](https://github.com/barzkit/
|
|
176
|
+
[Documentation](https://github.com/barzkit/docs) · [Examples](https://github.com/barzkit/examples) · [Trust Wallet Barz](https://github.com/trustwallet/barz)
|
package/dist/index.cjs
CHANGED
|
@@ -88,6 +88,12 @@ var TransactionError = class extends BarzKitError {
|
|
|
88
88
|
this.txHash = txHash;
|
|
89
89
|
}
|
|
90
90
|
};
|
|
91
|
+
var X402Error = class extends BarzKitError {
|
|
92
|
+
constructor(message) {
|
|
93
|
+
super(message, "X402_ERROR");
|
|
94
|
+
this.name = "X402Error";
|
|
95
|
+
}
|
|
96
|
+
};
|
|
91
97
|
var BundlerError = class extends BarzKitError {
|
|
92
98
|
constructor(message) {
|
|
93
99
|
super(message, "BUNDLER_ERROR");
|
|
@@ -318,6 +324,362 @@ var ERC20_ABI = [
|
|
|
318
324
|
type: "function"
|
|
319
325
|
}
|
|
320
326
|
];
|
|
327
|
+
var ETH_SENTINEL = "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE";
|
|
328
|
+
var TOKEN_DECIMALS = {
|
|
329
|
+
ETH: 18,
|
|
330
|
+
WETH: 18,
|
|
331
|
+
USDC: 6,
|
|
332
|
+
USDT: 6,
|
|
333
|
+
DAI: 18,
|
|
334
|
+
USDbC: 6
|
|
335
|
+
};
|
|
336
|
+
function resolveToken(symbolOrAddress, chain) {
|
|
337
|
+
if (symbolOrAddress.startsWith("0x")) {
|
|
338
|
+
return viem.getAddress(symbolOrAddress);
|
|
339
|
+
}
|
|
340
|
+
const symbol = symbolOrAddress.toUpperCase();
|
|
341
|
+
if (symbol === "ETH") {
|
|
342
|
+
return ETH_SENTINEL;
|
|
343
|
+
}
|
|
344
|
+
const chainTokens = TOKENS[chain];
|
|
345
|
+
if (!chainTokens) {
|
|
346
|
+
throw new BarzKitError(
|
|
347
|
+
`No tokens configured for chain "${chain}".`,
|
|
348
|
+
"UNSUPPORTED_CHAIN"
|
|
349
|
+
);
|
|
350
|
+
}
|
|
351
|
+
const address = chainTokens[symbol];
|
|
352
|
+
if (!address) {
|
|
353
|
+
throw new BarzKitError(
|
|
354
|
+
`Unknown token "${symbolOrAddress}" on ${chain}. Available: ${Object.keys(chainTokens).join(", ")}`,
|
|
355
|
+
"UNKNOWN_TOKEN"
|
|
356
|
+
);
|
|
357
|
+
}
|
|
358
|
+
return address;
|
|
359
|
+
}
|
|
360
|
+
function getTokenDecimals(symbol) {
|
|
361
|
+
return TOKEN_DECIMALS[symbol.toUpperCase()] ?? null;
|
|
362
|
+
}
|
|
363
|
+
function isNativeETH(token) {
|
|
364
|
+
if (token.toUpperCase() === "ETH") return true;
|
|
365
|
+
if (token.startsWith("0x")) {
|
|
366
|
+
return token.toLowerCase() === ETH_SENTINEL.toLowerCase();
|
|
367
|
+
}
|
|
368
|
+
return false;
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
// src/actions/swap.ts
|
|
372
|
+
var UNISWAP_V3_ROUTER = {
|
|
373
|
+
sepolia: "0x3bFA4769FB09eefC5a80d6E87c3B9C650f7Ae48E"
|
|
374
|
+
};
|
|
375
|
+
var SWAP_ROUTER_ABI = [
|
|
376
|
+
{
|
|
377
|
+
inputs: [
|
|
378
|
+
{
|
|
379
|
+
components: [
|
|
380
|
+
{ name: "tokenIn", type: "address" },
|
|
381
|
+
{ name: "tokenOut", type: "address" },
|
|
382
|
+
{ name: "fee", type: "uint24" },
|
|
383
|
+
{ name: "recipient", type: "address" },
|
|
384
|
+
{ name: "amountIn", type: "uint256" },
|
|
385
|
+
{ name: "amountOutMinimum", type: "uint256" },
|
|
386
|
+
{ name: "sqrtPriceLimitX96", type: "uint160" }
|
|
387
|
+
],
|
|
388
|
+
name: "params",
|
|
389
|
+
type: "tuple"
|
|
390
|
+
}
|
|
391
|
+
],
|
|
392
|
+
name: "exactInputSingle",
|
|
393
|
+
outputs: [{ name: "amountOut", type: "uint256" }],
|
|
394
|
+
stateMutability: "payable",
|
|
395
|
+
type: "function"
|
|
396
|
+
}
|
|
397
|
+
];
|
|
398
|
+
function buildSwapTransactions(params, chain, account) {
|
|
399
|
+
const router = UNISWAP_V3_ROUTER[chain];
|
|
400
|
+
if (!router) {
|
|
401
|
+
throw new BarzKitError(
|
|
402
|
+
`Uniswap V3 is not available on "${chain}". Supported: ${Object.keys(UNISWAP_V3_ROUTER).join(", ")}`,
|
|
403
|
+
"UNSUPPORTED_CHAIN"
|
|
404
|
+
);
|
|
405
|
+
}
|
|
406
|
+
const tokenIn = resolveToken(params.from, chain);
|
|
407
|
+
const tokenOut = resolveToken(params.to, chain);
|
|
408
|
+
if (tokenIn.toLowerCase() === tokenOut.toLowerCase()) {
|
|
409
|
+
throw new BarzKitError(
|
|
410
|
+
`Cannot swap a token to itself ("${params.from}" \u2192 "${params.to}").`,
|
|
411
|
+
"INVALID_SWAP"
|
|
412
|
+
);
|
|
413
|
+
}
|
|
414
|
+
const fromIsETH = isNativeETH(params.from);
|
|
415
|
+
const fromSymbol = params.from.startsWith("0x") ? null : params.from;
|
|
416
|
+
const decimals = fromSymbol ? getTokenDecimals(fromSymbol) ?? 18 : 18;
|
|
417
|
+
const amountIn = viem.parseUnits(params.amount, decimals);
|
|
418
|
+
const routerTokenIn = fromIsETH ? resolveToken("WETH", chain) : tokenIn;
|
|
419
|
+
const routerTokenOut = isNativeETH(params.to) ? resolveToken("WETH", chain) : tokenOut;
|
|
420
|
+
const fee = params.fee ?? 3e3;
|
|
421
|
+
const amountOutMinimum = 0n;
|
|
422
|
+
const swapData = viem.encodeFunctionData({
|
|
423
|
+
abi: SWAP_ROUTER_ABI,
|
|
424
|
+
functionName: "exactInputSingle",
|
|
425
|
+
args: [
|
|
426
|
+
{
|
|
427
|
+
tokenIn: routerTokenIn,
|
|
428
|
+
tokenOut: routerTokenOut,
|
|
429
|
+
fee,
|
|
430
|
+
recipient: account,
|
|
431
|
+
amountIn,
|
|
432
|
+
amountOutMinimum,
|
|
433
|
+
sqrtPriceLimitX96: 0n
|
|
434
|
+
}
|
|
435
|
+
]
|
|
436
|
+
});
|
|
437
|
+
const txs = [];
|
|
438
|
+
if (fromIsETH) {
|
|
439
|
+
txs.push({
|
|
440
|
+
to: router,
|
|
441
|
+
value: amountIn,
|
|
442
|
+
data: swapData
|
|
443
|
+
});
|
|
444
|
+
} else {
|
|
445
|
+
const approveData = viem.encodeFunctionData({
|
|
446
|
+
abi: ERC20_ABI,
|
|
447
|
+
functionName: "approve",
|
|
448
|
+
args: [router, amountIn]
|
|
449
|
+
});
|
|
450
|
+
txs.push({
|
|
451
|
+
to: tokenIn,
|
|
452
|
+
data: approveData
|
|
453
|
+
});
|
|
454
|
+
txs.push({
|
|
455
|
+
to: router,
|
|
456
|
+
data: swapData
|
|
457
|
+
});
|
|
458
|
+
}
|
|
459
|
+
return txs;
|
|
460
|
+
}
|
|
461
|
+
function getSwapTokenAddresses(params, chain) {
|
|
462
|
+
const addresses = [];
|
|
463
|
+
const tokenIn = resolveToken(params.from, chain);
|
|
464
|
+
const tokenOut = resolveToken(params.to, chain);
|
|
465
|
+
if (tokenIn !== ETH_SENTINEL) addresses.push(tokenIn);
|
|
466
|
+
if (tokenOut !== ETH_SENTINEL) addresses.push(tokenOut);
|
|
467
|
+
return addresses;
|
|
468
|
+
}
|
|
469
|
+
var AAVE_V3_POOL = {
|
|
470
|
+
sepolia: "0x6Ae43d3271ff6888e7Fc43Fd7321a503ff738951"
|
|
471
|
+
};
|
|
472
|
+
var AAVE_POOL_ABI = [
|
|
473
|
+
{
|
|
474
|
+
inputs: [
|
|
475
|
+
{ name: "asset", type: "address" },
|
|
476
|
+
{ name: "amount", type: "uint256" },
|
|
477
|
+
{ name: "onBehalfOf", type: "address" },
|
|
478
|
+
{ name: "referralCode", type: "uint16" }
|
|
479
|
+
],
|
|
480
|
+
name: "supply",
|
|
481
|
+
outputs: [],
|
|
482
|
+
stateMutability: "nonpayable",
|
|
483
|
+
type: "function"
|
|
484
|
+
}
|
|
485
|
+
];
|
|
486
|
+
function buildLendTransactions(params, chain, account) {
|
|
487
|
+
if (params.protocol !== "aave") {
|
|
488
|
+
throw new BarzKitError(
|
|
489
|
+
`Unknown lending protocol "${params.protocol}". Supported: aave`,
|
|
490
|
+
"UNKNOWN_PROTOCOL"
|
|
491
|
+
);
|
|
492
|
+
}
|
|
493
|
+
const pool = AAVE_V3_POOL[chain];
|
|
494
|
+
if (!pool) {
|
|
495
|
+
throw new BarzKitError(
|
|
496
|
+
`Aave V3 is not available on "${chain}". Supported: ${Object.keys(AAVE_V3_POOL).join(", ")}`,
|
|
497
|
+
"UNSUPPORTED_CHAIN"
|
|
498
|
+
);
|
|
499
|
+
}
|
|
500
|
+
if (isNativeETH(params.token)) {
|
|
501
|
+
throw new BarzKitError(
|
|
502
|
+
"Cannot supply native ETH to Aave. Wrap to WETH first, then supply WETH.",
|
|
503
|
+
"NATIVE_ETH_NOT_SUPPORTED"
|
|
504
|
+
);
|
|
505
|
+
}
|
|
506
|
+
const tokenAddress = resolveToken(params.token, chain);
|
|
507
|
+
const tokenSymbol = params.token.startsWith("0x") ? null : params.token;
|
|
508
|
+
const decimals = tokenSymbol ? getTokenDecimals(tokenSymbol) ?? 18 : 18;
|
|
509
|
+
const amount = viem.parseUnits(params.amount, decimals);
|
|
510
|
+
const approveData = viem.encodeFunctionData({
|
|
511
|
+
abi: ERC20_ABI,
|
|
512
|
+
functionName: "approve",
|
|
513
|
+
args: [pool, amount]
|
|
514
|
+
});
|
|
515
|
+
const supplyData = viem.encodeFunctionData({
|
|
516
|
+
abi: AAVE_POOL_ABI,
|
|
517
|
+
functionName: "supply",
|
|
518
|
+
args: [tokenAddress, amount, account, 0]
|
|
519
|
+
});
|
|
520
|
+
return [
|
|
521
|
+
{
|
|
522
|
+
to: tokenAddress,
|
|
523
|
+
data: approveData
|
|
524
|
+
},
|
|
525
|
+
{
|
|
526
|
+
to: pool,
|
|
527
|
+
data: supplyData
|
|
528
|
+
}
|
|
529
|
+
];
|
|
530
|
+
}
|
|
531
|
+
function getLendTokenAddresses(params, chain) {
|
|
532
|
+
const tokenAddress = resolveToken(params.token, chain);
|
|
533
|
+
return [tokenAddress];
|
|
534
|
+
}
|
|
535
|
+
var HEADER_AMOUNT = "x-payment-amount";
|
|
536
|
+
var HEADER_ADDRESS = "x-payment-address";
|
|
537
|
+
var HEADER_TOKEN = "x-payment-token";
|
|
538
|
+
var HEADER_NETWORK = "x-payment-network";
|
|
539
|
+
var HEADER_PROOF = "X-Payment-Proof";
|
|
540
|
+
function parsePaymentRequired(response) {
|
|
541
|
+
const amount = response.headers.get(HEADER_AMOUNT);
|
|
542
|
+
const address = response.headers.get(HEADER_ADDRESS);
|
|
543
|
+
const token = response.headers.get(HEADER_TOKEN);
|
|
544
|
+
const network = response.headers.get(HEADER_NETWORK);
|
|
545
|
+
if (!amount || !address || !token || !network) {
|
|
546
|
+
const missing = [
|
|
547
|
+
!amount && "X-Payment-Amount",
|
|
548
|
+
!address && "X-Payment-Address",
|
|
549
|
+
!token && "X-Payment-Token",
|
|
550
|
+
!network && "X-Payment-Network"
|
|
551
|
+
].filter(Boolean);
|
|
552
|
+
throw new X402Error(`402 response missing required headers: ${missing.join(", ")}`);
|
|
553
|
+
}
|
|
554
|
+
const parsed = BigInt(amount);
|
|
555
|
+
if (parsed <= 0n) {
|
|
556
|
+
throw new X402Error(`Invalid payment amount: ${amount}`);
|
|
557
|
+
}
|
|
558
|
+
return {
|
|
559
|
+
amount: parsed,
|
|
560
|
+
address,
|
|
561
|
+
token,
|
|
562
|
+
network
|
|
563
|
+
};
|
|
564
|
+
}
|
|
565
|
+
function validateDomain(url, allowedDomains) {
|
|
566
|
+
if (!allowedDomains || allowedDomains.length === 0) return;
|
|
567
|
+
const hostname = new URL(url).hostname;
|
|
568
|
+
if (!allowedDomains.includes(hostname)) {
|
|
569
|
+
throw new X402Error(
|
|
570
|
+
`Domain "${hostname}" is not in the allowed list. Allowed: ${allowedDomains.join(", ")}`
|
|
571
|
+
);
|
|
572
|
+
}
|
|
573
|
+
}
|
|
574
|
+
var X402Manager = class {
|
|
575
|
+
_config = null;
|
|
576
|
+
_dailySpent = 0n;
|
|
577
|
+
_windowStart = 0;
|
|
578
|
+
get enabled() {
|
|
579
|
+
return this._config !== null;
|
|
580
|
+
}
|
|
581
|
+
get config() {
|
|
582
|
+
return this._config;
|
|
583
|
+
}
|
|
584
|
+
get dailySpent() {
|
|
585
|
+
this.resetIfExpired();
|
|
586
|
+
return this._dailySpent;
|
|
587
|
+
}
|
|
588
|
+
enable(config) {
|
|
589
|
+
this._config = config;
|
|
590
|
+
this._dailySpent = 0n;
|
|
591
|
+
this._windowStart = Date.now();
|
|
592
|
+
}
|
|
593
|
+
validatePayment(amount) {
|
|
594
|
+
if (!this._config) throw new X402Error("x402 not enabled");
|
|
595
|
+
this.resetIfExpired();
|
|
596
|
+
const maxPerRequest = parseHumanAmountToAtomic(this._config.maxPaymentPerRequest);
|
|
597
|
+
if (amount > maxPerRequest) {
|
|
598
|
+
throw new PermissionError(
|
|
599
|
+
`Payment amount ${amount} exceeds per-request limit of ${maxPerRequest} (${this._config.maxPaymentPerRequest})`
|
|
600
|
+
);
|
|
601
|
+
}
|
|
602
|
+
const maxDaily = parseHumanAmountToAtomic(this._config.maxDailyPayments);
|
|
603
|
+
if (this._dailySpent + amount > maxDaily) {
|
|
604
|
+
throw new PermissionError(
|
|
605
|
+
`Payment would exceed daily limit of ${maxDaily} (${this._config.maxDailyPayments}). Already spent: ${this._dailySpent}`
|
|
606
|
+
);
|
|
607
|
+
}
|
|
608
|
+
}
|
|
609
|
+
recordPayment(amount) {
|
|
610
|
+
this.resetIfExpired();
|
|
611
|
+
this._dailySpent += amount;
|
|
612
|
+
}
|
|
613
|
+
resetIfExpired() {
|
|
614
|
+
const now = Date.now();
|
|
615
|
+
const elapsed = now - this._windowStart;
|
|
616
|
+
const DAY_MS = 24 * 60 * 60 * 1e3;
|
|
617
|
+
if (elapsed >= DAY_MS) {
|
|
618
|
+
this._dailySpent = 0n;
|
|
619
|
+
this._windowStart = now;
|
|
620
|
+
}
|
|
621
|
+
}
|
|
622
|
+
};
|
|
623
|
+
function buildPaymentTransaction(payment) {
|
|
624
|
+
const data = viem.encodeFunctionData({
|
|
625
|
+
abi: ERC20_ABI,
|
|
626
|
+
functionName: "transfer",
|
|
627
|
+
args: [payment.address, payment.amount]
|
|
628
|
+
});
|
|
629
|
+
return {
|
|
630
|
+
to: payment.token,
|
|
631
|
+
data
|
|
632
|
+
};
|
|
633
|
+
}
|
|
634
|
+
function createFetchWithPayment(manager, sendTransaction) {
|
|
635
|
+
return async function fetchWithPayment(url, options) {
|
|
636
|
+
if (!manager.enabled) {
|
|
637
|
+
throw new X402Error("x402 not enabled. Call agent.enableX402() first.");
|
|
638
|
+
}
|
|
639
|
+
const config = manager.config;
|
|
640
|
+
validateDomain(url, config.allowedDomains);
|
|
641
|
+
const response = await fetch(url, options);
|
|
642
|
+
if (response.status !== 402) {
|
|
643
|
+
return response;
|
|
644
|
+
}
|
|
645
|
+
const payment = parsePaymentRequired(response);
|
|
646
|
+
manager.validatePayment(payment.amount);
|
|
647
|
+
const txHash = await sendTransaction(buildPaymentTransaction(payment));
|
|
648
|
+
manager.recordPayment(payment.amount);
|
|
649
|
+
return fetch(url, {
|
|
650
|
+
...options,
|
|
651
|
+
headers: {
|
|
652
|
+
...options?.headers,
|
|
653
|
+
[HEADER_PROOF]: txHash
|
|
654
|
+
}
|
|
655
|
+
});
|
|
656
|
+
};
|
|
657
|
+
}
|
|
658
|
+
function parseHumanAmountToAtomic(input) {
|
|
659
|
+
const parts = input.trim().split(/\s+/);
|
|
660
|
+
if (parts.length !== 2) {
|
|
661
|
+
throw new X402Error(`Invalid amount format: "${input}". Expected "0.01 USDC".`);
|
|
662
|
+
}
|
|
663
|
+
const [numStr, unit] = parts;
|
|
664
|
+
const upper = unit.toUpperCase();
|
|
665
|
+
let decimals;
|
|
666
|
+
switch (upper) {
|
|
667
|
+
case "USDC":
|
|
668
|
+
case "USDT":
|
|
669
|
+
decimals = 6;
|
|
670
|
+
break;
|
|
671
|
+
case "DAI":
|
|
672
|
+
case "ETH":
|
|
673
|
+
case "WETH":
|
|
674
|
+
decimals = 18;
|
|
675
|
+
break;
|
|
676
|
+
default:
|
|
677
|
+
throw new X402Error(`Unknown token unit in amount: "${unit}"`);
|
|
678
|
+
}
|
|
679
|
+
const [whole, frac = ""] = numStr.split(".");
|
|
680
|
+
const padded = frac.padEnd(decimals, "0").slice(0, decimals);
|
|
681
|
+
return BigInt(whole + padded);
|
|
682
|
+
}
|
|
321
683
|
|
|
322
684
|
// src/core/account.ts
|
|
323
685
|
async function createBarzAgent(config) {
|
|
@@ -353,7 +715,30 @@ async function createBarzAgent(config) {
|
|
|
353
715
|
console.warn("\u26A0\uFE0F Using Base mainnet \u2014 real funds at risk");
|
|
354
716
|
}
|
|
355
717
|
const permissionManager = new PermissionManager(config.permissions);
|
|
718
|
+
const x402Manager = new X402Manager();
|
|
356
719
|
let frozen = false;
|
|
720
|
+
async function executeBatch(txs) {
|
|
721
|
+
for (const tx of txs) {
|
|
722
|
+
permissionManager.validate(tx);
|
|
723
|
+
}
|
|
724
|
+
try {
|
|
725
|
+
const userOpHash = await smartAccountClient.sendUserOperation({
|
|
726
|
+
calls: txs.map((tx) => ({
|
|
727
|
+
to: tx.to,
|
|
728
|
+
value: tx.value ?? 0n,
|
|
729
|
+
data: tx.data ?? "0x"
|
|
730
|
+
}))
|
|
731
|
+
});
|
|
732
|
+
const receipt = await smartAccountClient.waitForUserOperationReceipt({
|
|
733
|
+
hash: userOpHash
|
|
734
|
+
});
|
|
735
|
+
const totalValue = txs.reduce((sum, tx) => sum + (tx.value ?? 0n), 0n);
|
|
736
|
+
if (totalValue > 0n) permissionManager.recordSpend(totalValue);
|
|
737
|
+
return receipt.receipt.transactionHash;
|
|
738
|
+
} catch (error) {
|
|
739
|
+
throw humanizeError(error);
|
|
740
|
+
}
|
|
741
|
+
}
|
|
357
742
|
const agent = {
|
|
358
743
|
address: smartAccount.address,
|
|
359
744
|
chain: config.chain,
|
|
@@ -381,26 +766,7 @@ async function createBarzAgent(config) {
|
|
|
381
766
|
"BATCH_EMPTY"
|
|
382
767
|
);
|
|
383
768
|
}
|
|
384
|
-
|
|
385
|
-
permissionManager.validate(tx);
|
|
386
|
-
}
|
|
387
|
-
try {
|
|
388
|
-
const userOpHash = await smartAccountClient.sendUserOperation({
|
|
389
|
-
calls: txs.map((tx) => ({
|
|
390
|
-
to: tx.to,
|
|
391
|
-
value: tx.value ?? 0n,
|
|
392
|
-
data: tx.data ?? "0x"
|
|
393
|
-
}))
|
|
394
|
-
});
|
|
395
|
-
const receipt = await smartAccountClient.waitForUserOperationReceipt({
|
|
396
|
-
hash: userOpHash
|
|
397
|
-
});
|
|
398
|
-
const totalValue = txs.reduce((sum, tx) => sum + (tx.value ?? 0n), 0n);
|
|
399
|
-
if (totalValue > 0n) permissionManager.recordSpend(totalValue);
|
|
400
|
-
return receipt.receipt.transactionHash;
|
|
401
|
-
} catch (error) {
|
|
402
|
-
throw humanizeError(error);
|
|
403
|
-
}
|
|
769
|
+
return executeBatch(txs);
|
|
404
770
|
},
|
|
405
771
|
async getBalance(token) {
|
|
406
772
|
try {
|
|
@@ -434,6 +800,24 @@ async function createBarzAgent(config) {
|
|
|
434
800
|
);
|
|
435
801
|
}
|
|
436
802
|
},
|
|
803
|
+
async swap(params) {
|
|
804
|
+
if (frozen) throw new FrozenError();
|
|
805
|
+
const tokenAddresses = getSwapTokenAddresses(params, config.chain);
|
|
806
|
+
validateTokenPermissions(tokenAddresses, permissionManager.permissions);
|
|
807
|
+
const txs = buildSwapTransactions(params, config.chain, smartAccount.address);
|
|
808
|
+
return executeBatch(txs);
|
|
809
|
+
},
|
|
810
|
+
async lend(params) {
|
|
811
|
+
if (frozen) throw new FrozenError();
|
|
812
|
+
const tokenAddresses = getLendTokenAddresses(params, config.chain);
|
|
813
|
+
validateTokenPermissions(tokenAddresses, permissionManager.permissions);
|
|
814
|
+
const txs = buildLendTransactions(params, config.chain, smartAccount.address);
|
|
815
|
+
return executeBatch(txs);
|
|
816
|
+
},
|
|
817
|
+
enableX402(x402Config) {
|
|
818
|
+
x402Manager.enable(x402Config);
|
|
819
|
+
},
|
|
820
|
+
fetchWithPayment: null,
|
|
437
821
|
getExplorerUrl(hash) {
|
|
438
822
|
return `${chainConfig.explorerUrl}/tx/${hash}`;
|
|
439
823
|
},
|
|
@@ -455,6 +839,10 @@ async function createBarzAgent(config) {
|
|
|
455
839
|
return !frozen;
|
|
456
840
|
}
|
|
457
841
|
};
|
|
842
|
+
agent.fetchWithPayment = createFetchWithPayment(
|
|
843
|
+
x402Manager,
|
|
844
|
+
(tx) => agent.sendTransaction(tx)
|
|
845
|
+
);
|
|
458
846
|
return agent;
|
|
459
847
|
}
|
|
460
848
|
function validateConfig(config) {
|
|
@@ -474,17 +862,44 @@ function validateConfig(config) {
|
|
|
474
862
|
throw new ConfigError('Missing "pimlico.apiKey". Get a free key at https://dashboard.pimlico.io');
|
|
475
863
|
}
|
|
476
864
|
}
|
|
865
|
+
function validateTokenPermissions(tokenAddresses, permissions) {
|
|
866
|
+
if (!permissions.allowedTokens || permissions.allowedTokens.length === 0) return;
|
|
867
|
+
const allowed = permissions.allowedTokens.map((a) => a.toLowerCase());
|
|
868
|
+
for (const token of tokenAddresses) {
|
|
869
|
+
if (!allowed.includes(token.toLowerCase())) {
|
|
870
|
+
throw new PermissionError(
|
|
871
|
+
`Token ${token} is not in the allowed list. Allowed: ${permissions.allowedTokens.join(", ")}`
|
|
872
|
+
);
|
|
873
|
+
}
|
|
874
|
+
}
|
|
875
|
+
}
|
|
477
876
|
|
|
877
|
+
exports.AAVE_V3_POOL = AAVE_V3_POOL;
|
|
478
878
|
exports.BarzKitError = BarzKitError;
|
|
479
879
|
exports.BundlerError = BundlerError;
|
|
480
880
|
exports.CHAIN_CONFIGS = CHAIN_CONFIGS;
|
|
481
881
|
exports.ConfigError = ConfigError;
|
|
482
882
|
exports.ERC20_ABI = ERC20_ABI;
|
|
883
|
+
exports.ETH_SENTINEL = ETH_SENTINEL;
|
|
483
884
|
exports.FrozenError = FrozenError;
|
|
484
885
|
exports.PermissionError = PermissionError;
|
|
485
886
|
exports.TOKENS = TOKENS;
|
|
486
887
|
exports.TransactionError = TransactionError;
|
|
888
|
+
exports.UNISWAP_V3_ROUTER = UNISWAP_V3_ROUTER;
|
|
889
|
+
exports.X402Error = X402Error;
|
|
890
|
+
exports.X402Manager = X402Manager;
|
|
891
|
+
exports.buildLendTransactions = buildLendTransactions;
|
|
892
|
+
exports.buildPaymentTransaction = buildPaymentTransaction;
|
|
893
|
+
exports.buildSwapTransactions = buildSwapTransactions;
|
|
487
894
|
exports.createBarzAgent = createBarzAgent;
|
|
895
|
+
exports.createFetchWithPayment = createFetchWithPayment;
|
|
488
896
|
exports.getChainConfig = getChainConfig;
|
|
897
|
+
exports.getLendTokenAddresses = getLendTokenAddresses;
|
|
898
|
+
exports.getSwapTokenAddresses = getSwapTokenAddresses;
|
|
899
|
+
exports.getTokenDecimals = getTokenDecimals;
|
|
900
|
+
exports.isNativeETH = isNativeETH;
|
|
901
|
+
exports.parsePaymentRequired = parsePaymentRequired;
|
|
902
|
+
exports.resolveToken = resolveToken;
|
|
903
|
+
exports.validateDomain = validateDomain;
|
|
489
904
|
//# sourceMappingURL=index.cjs.map
|
|
490
905
|
//# sourceMappingURL=index.cjs.map
|