@barzkit/sdk 0.1.1 → 0.1.3

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 ADDED
@@ -0,0 +1,92 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [0.1.3] - 2026-03-01
9
+
10
+ ### Added
11
+
12
+ - `swap()` method on `BarzAgent` — swap tokens via Uniswap V3 (Sepolia)
13
+ - `lend()` method on `BarzAgent` — supply tokens to Aave V3 (Sepolia)
14
+ - `SwapParams` and `LendParams` interfaces
15
+ - `src/actions/tokens.ts` — `resolveToken()`, `getTokenDecimals()`, `isNativeETH()`, `ETH_SENTINEL`
16
+ - `src/actions/swap.ts` — `buildSwapTransactions()`, `getSwapTokenAddresses()`, `UNISWAP_V3_ROUTER`
17
+ - `src/actions/lend.ts` — `buildLendTransactions()`, `getLendTokenAddresses()`, `AAVE_V3_POOL`
18
+ - Token permission validation for DeFi actions (`allowedTokens` check)
19
+ - Unit tests for tokens, swap, and lend calldata builders
20
+ - `defi-agent` example
21
+ - DeFi actions guide (`docs/guides/defi-actions.md`)
22
+
23
+ ### Changed
24
+
25
+ - Extracted `executeBatch()` helper in `account.ts` (reused by `batchTransactions`, `swap`, `lend`)
26
+
27
+ ## [0.1.2] - 2026-03-01
28
+
29
+ ### Added
30
+
31
+ - `explorerUrl` field in `ChainConfig` — block explorer base URL per chain
32
+ - `getExplorerUrl(hash)` method on `BarzAgent` — returns full explorer link for a transaction
33
+ - Console warning when using Base mainnet (real funds at risk)
34
+ - Chain-specific unit tests (`tests/unit/chains.test.ts`)
35
+
36
+ ### Changed
37
+
38
+ - Updated package description and keywords for better discoverability
39
+ - Refactored chain tests into dedicated test file
40
+
41
+ ## [0.1.1] - 2026-03-01
42
+
43
+ ### Added
44
+
45
+ - `batchTransactions()` — atomic multi-call in a single UserOperation
46
+
47
+ ## [0.1.0] - 2026-02-28
48
+
49
+ ### Added
50
+
51
+ #### Core API
52
+
53
+ - `createBarzAgent()` — create an ERC-4337 smart account wallet on any supported chain
54
+ - `sendTransaction()` — send gasless transactions via Pimlico bundler + paymaster
55
+ - `getBalance()` — query ETH and ERC-20 token balances
56
+ - `waitForTransaction()` — wait for on-chain confirmation with structured `TransactionReceipt`
57
+ - `getExplorerUrl()` — block explorer URL for any transaction hash
58
+
59
+ #### Multi-chain
60
+
61
+ - Chain support: Sepolia, Base Sepolia, Base mainnet
62
+ - `CHAIN_CONFIGS` / `getChainConfig` — chain configuration registry
63
+ - `TOKENS` — pre-configured token addresses (USDC, WETH, DAI) per chain
64
+ - Custom `rpcUrl` option in `AgentConfig`
65
+ - Console warning when using Base mainnet (real funds at risk)
66
+
67
+ #### Permissions
68
+
69
+ - `AgentPermissions` — spending limits, contract whitelists, time windows
70
+ - `getPermissions()` / `updatePermissions()` — runtime permission management
71
+ - Client-side validation: per-tx limit, daily spend cap, allowed contracts, time window
72
+
73
+ #### Safety
74
+
75
+ - `freeze()` / `unfreeze()` — client-side kill switch (Phase 1)
76
+ - `isActive()` — check whether the agent wallet is frozen
77
+
78
+ #### DX
79
+
80
+ - Human-readable AA error mapping (AA21, AA25, AA31, AA33, AA40/41)
81
+ - Typed error hierarchy: `BarzKitError`, `ConfigError`, `PermissionError`, `FrozenError`, `TransactionError`, `BundlerError`
82
+ - Config validation with actionable error messages
83
+ - Account `index` for deterministic multi-wallet derivation from the same owner key
84
+ - `gasless` config option (default: `true`)
85
+ - `ERC20_ABI` — common ERC-20 function ABIs for contract reads
86
+ - `AgentEvent` type definitions for future event hooks
87
+ - Dual-package build: ESM (`.mjs`) + CJS (`.js`) + DTS (`.d.ts`)
88
+
89
+ [0.1.3]: https://github.com/barzkit/sdk/compare/v0.1.2...v0.1.3
90
+ [0.1.2]: https://github.com/barzkit/sdk/compare/v0.1.1...v0.1.2
91
+ [0.1.1]: https://github.com/barzkit/sdk/compare/v0.1.0...v0.1.1
92
+ [0.1.0]: https://github.com/barzkit/sdk/releases/tag/v0.1.0
package/README.md CHANGED
@@ -142,7 +142,7 @@ Your AI Agent
142
142
 
143
143
  ## Examples
144
144
 
145
- See [barzkit-examples](https://github.com/barzkit/examples) for complete working examples.
145
+ See [examples](https://github.com/barzkit/examples) for complete working examples.
146
146
 
147
147
  ## Security
148
148
 
@@ -156,8 +156,8 @@ See [barzkit-examples](https://github.com/barzkit/examples) for complete working
156
156
 
157
157
  - [x] Core SDK: createWallet, sendTransaction, permissions, freeze
158
158
  - [x] Batch transactions: atomic multi-call in one UserOperation
159
- - [ ] Multi-chain: Base Sepolia, Base mainnet
160
- - [ ] DeFi actions: swap, lend (Uniswap, Aave)
159
+ - [x] Multi-chain: Base Sepolia, Base mainnet
160
+ - [x] DeFi actions: swap, lend (Uniswap, Aave)
161
161
  - [ ] ElizaOS plugin
162
162
  - [ ] LangChain tool
163
163
  - [ ] x402 payment handler
@@ -173,4 +173,4 @@ MIT
173
173
 
174
174
  ---
175
175
 
176
- [Documentation](https://github.com/barzkit/sdk) · [Examples](https://github.com/barzkit/examples) · [Trust Wallet Barz](https://github.com/trustwallet/barz)
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
@@ -16,7 +16,8 @@ var CHAIN_CONFIGS = {
16
16
  bundlerUrl: "https://api.pimlico.io/v2/sepolia/rpc",
17
17
  paymasterUrl: "https://api.pimlico.io/v2/sepolia/rpc",
18
18
  entryPointAddress: "0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789",
19
- entryPointVersion: "0.6"
19
+ entryPointVersion: "0.6",
20
+ explorerUrl: "https://sepolia.etherscan.io"
20
21
  },
21
22
  "base-sepolia": {
22
23
  chain: chains.baseSepolia,
@@ -24,7 +25,8 @@ var CHAIN_CONFIGS = {
24
25
  bundlerUrl: "https://api.pimlico.io/v2/base-sepolia/rpc",
25
26
  paymasterUrl: "https://api.pimlico.io/v2/base-sepolia/rpc",
26
27
  entryPointAddress: "0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789",
27
- entryPointVersion: "0.6"
28
+ entryPointVersion: "0.6",
29
+ explorerUrl: "https://sepolia.basescan.org"
28
30
  },
29
31
  base: {
30
32
  chain: chains.base,
@@ -32,7 +34,8 @@ var CHAIN_CONFIGS = {
32
34
  bundlerUrl: "https://api.pimlico.io/v2/base/rpc",
33
35
  paymasterUrl: "https://api.pimlico.io/v2/base/rpc",
34
36
  entryPointAddress: "0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789",
35
- entryPointVersion: "0.6"
37
+ entryPointVersion: "0.6",
38
+ explorerUrl: "https://basescan.org"
36
39
  }
37
40
  };
38
41
  function getChainConfig(chain) {
@@ -315,6 +318,214 @@ var ERC20_ABI = [
315
318
  type: "function"
316
319
  }
317
320
  ];
321
+ var ETH_SENTINEL = "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE";
322
+ var TOKEN_DECIMALS = {
323
+ ETH: 18,
324
+ WETH: 18,
325
+ USDC: 6,
326
+ USDT: 6,
327
+ DAI: 18,
328
+ USDbC: 6
329
+ };
330
+ function resolveToken(symbolOrAddress, chain) {
331
+ if (symbolOrAddress.startsWith("0x")) {
332
+ return viem.getAddress(symbolOrAddress);
333
+ }
334
+ const symbol = symbolOrAddress.toUpperCase();
335
+ if (symbol === "ETH") {
336
+ return ETH_SENTINEL;
337
+ }
338
+ const chainTokens = TOKENS[chain];
339
+ if (!chainTokens) {
340
+ throw new BarzKitError(
341
+ `No tokens configured for chain "${chain}".`,
342
+ "UNSUPPORTED_CHAIN"
343
+ );
344
+ }
345
+ const address = chainTokens[symbol];
346
+ if (!address) {
347
+ throw new BarzKitError(
348
+ `Unknown token "${symbolOrAddress}" on ${chain}. Available: ${Object.keys(chainTokens).join(", ")}`,
349
+ "UNKNOWN_TOKEN"
350
+ );
351
+ }
352
+ return address;
353
+ }
354
+ function getTokenDecimals(symbol) {
355
+ return TOKEN_DECIMALS[symbol.toUpperCase()] ?? null;
356
+ }
357
+ function isNativeETH(token) {
358
+ if (token.toUpperCase() === "ETH") return true;
359
+ if (token.startsWith("0x")) {
360
+ return token.toLowerCase() === ETH_SENTINEL.toLowerCase();
361
+ }
362
+ return false;
363
+ }
364
+
365
+ // src/actions/swap.ts
366
+ var UNISWAP_V3_ROUTER = {
367
+ sepolia: "0x3bFA4769FB09eefC5a80d6E87c3B9C650f7Ae48E"
368
+ };
369
+ var SWAP_ROUTER_ABI = [
370
+ {
371
+ inputs: [
372
+ {
373
+ components: [
374
+ { name: "tokenIn", type: "address" },
375
+ { name: "tokenOut", type: "address" },
376
+ { name: "fee", type: "uint24" },
377
+ { name: "recipient", type: "address" },
378
+ { name: "amountIn", type: "uint256" },
379
+ { name: "amountOutMinimum", type: "uint256" },
380
+ { name: "sqrtPriceLimitX96", type: "uint160" }
381
+ ],
382
+ name: "params",
383
+ type: "tuple"
384
+ }
385
+ ],
386
+ name: "exactInputSingle",
387
+ outputs: [{ name: "amountOut", type: "uint256" }],
388
+ stateMutability: "payable",
389
+ type: "function"
390
+ }
391
+ ];
392
+ function buildSwapTransactions(params, chain, account) {
393
+ const router = UNISWAP_V3_ROUTER[chain];
394
+ if (!router) {
395
+ throw new BarzKitError(
396
+ `Uniswap V3 is not available on "${chain}". Supported: ${Object.keys(UNISWAP_V3_ROUTER).join(", ")}`,
397
+ "UNSUPPORTED_CHAIN"
398
+ );
399
+ }
400
+ const tokenIn = resolveToken(params.from, chain);
401
+ const tokenOut = resolveToken(params.to, chain);
402
+ if (tokenIn.toLowerCase() === tokenOut.toLowerCase()) {
403
+ throw new BarzKitError(
404
+ `Cannot swap a token to itself ("${params.from}" \u2192 "${params.to}").`,
405
+ "INVALID_SWAP"
406
+ );
407
+ }
408
+ const fromIsETH = isNativeETH(params.from);
409
+ const fromSymbol = params.from.startsWith("0x") ? null : params.from;
410
+ const decimals = fromSymbol ? getTokenDecimals(fromSymbol) ?? 18 : 18;
411
+ const amountIn = viem.parseUnits(params.amount, decimals);
412
+ const routerTokenIn = fromIsETH ? resolveToken("WETH", chain) : tokenIn;
413
+ const routerTokenOut = isNativeETH(params.to) ? resolveToken("WETH", chain) : tokenOut;
414
+ const fee = params.fee ?? 3e3;
415
+ const amountOutMinimum = 0n;
416
+ const swapData = viem.encodeFunctionData({
417
+ abi: SWAP_ROUTER_ABI,
418
+ functionName: "exactInputSingle",
419
+ args: [
420
+ {
421
+ tokenIn: routerTokenIn,
422
+ tokenOut: routerTokenOut,
423
+ fee,
424
+ recipient: account,
425
+ amountIn,
426
+ amountOutMinimum,
427
+ sqrtPriceLimitX96: 0n
428
+ }
429
+ ]
430
+ });
431
+ const txs = [];
432
+ if (fromIsETH) {
433
+ txs.push({
434
+ to: router,
435
+ value: amountIn,
436
+ data: swapData
437
+ });
438
+ } else {
439
+ const approveData = viem.encodeFunctionData({
440
+ abi: ERC20_ABI,
441
+ functionName: "approve",
442
+ args: [router, amountIn]
443
+ });
444
+ txs.push({
445
+ to: tokenIn,
446
+ data: approveData
447
+ });
448
+ txs.push({
449
+ to: router,
450
+ data: swapData
451
+ });
452
+ }
453
+ return txs;
454
+ }
455
+ function getSwapTokenAddresses(params, chain) {
456
+ const addresses = [];
457
+ const tokenIn = resolveToken(params.from, chain);
458
+ const tokenOut = resolveToken(params.to, chain);
459
+ if (tokenIn !== ETH_SENTINEL) addresses.push(tokenIn);
460
+ if (tokenOut !== ETH_SENTINEL) addresses.push(tokenOut);
461
+ return addresses;
462
+ }
463
+ var AAVE_V3_POOL = {
464
+ sepolia: "0x6Ae43d3271ff6888e7Fc43Fd7321a503ff738951"
465
+ };
466
+ var AAVE_POOL_ABI = [
467
+ {
468
+ inputs: [
469
+ { name: "asset", type: "address" },
470
+ { name: "amount", type: "uint256" },
471
+ { name: "onBehalfOf", type: "address" },
472
+ { name: "referralCode", type: "uint16" }
473
+ ],
474
+ name: "supply",
475
+ outputs: [],
476
+ stateMutability: "nonpayable",
477
+ type: "function"
478
+ }
479
+ ];
480
+ function buildLendTransactions(params, chain, account) {
481
+ if (params.protocol !== "aave") {
482
+ throw new BarzKitError(
483
+ `Unknown lending protocol "${params.protocol}". Supported: aave`,
484
+ "UNKNOWN_PROTOCOL"
485
+ );
486
+ }
487
+ const pool = AAVE_V3_POOL[chain];
488
+ if (!pool) {
489
+ throw new BarzKitError(
490
+ `Aave V3 is not available on "${chain}". Supported: ${Object.keys(AAVE_V3_POOL).join(", ")}`,
491
+ "UNSUPPORTED_CHAIN"
492
+ );
493
+ }
494
+ if (isNativeETH(params.token)) {
495
+ throw new BarzKitError(
496
+ "Cannot supply native ETH to Aave. Wrap to WETH first, then supply WETH.",
497
+ "NATIVE_ETH_NOT_SUPPORTED"
498
+ );
499
+ }
500
+ const tokenAddress = resolveToken(params.token, chain);
501
+ const tokenSymbol = params.token.startsWith("0x") ? null : params.token;
502
+ const decimals = tokenSymbol ? getTokenDecimals(tokenSymbol) ?? 18 : 18;
503
+ const amount = viem.parseUnits(params.amount, decimals);
504
+ const approveData = viem.encodeFunctionData({
505
+ abi: ERC20_ABI,
506
+ functionName: "approve",
507
+ args: [pool, amount]
508
+ });
509
+ const supplyData = viem.encodeFunctionData({
510
+ abi: AAVE_POOL_ABI,
511
+ functionName: "supply",
512
+ args: [tokenAddress, amount, account, 0]
513
+ });
514
+ return [
515
+ {
516
+ to: tokenAddress,
517
+ data: approveData
518
+ },
519
+ {
520
+ to: pool,
521
+ data: supplyData
522
+ }
523
+ ];
524
+ }
525
+ function getLendTokenAddresses(params, chain) {
526
+ const tokenAddress = resolveToken(params.token, chain);
527
+ return [tokenAddress];
528
+ }
318
529
 
319
530
  // src/core/account.ts
320
531
  async function createBarzAgent(config) {
@@ -346,8 +557,33 @@ async function createBarzAgent(config) {
346
557
  }
347
558
  }
348
559
  });
560
+ if (config.chain === "base") {
561
+ console.warn("\u26A0\uFE0F Using Base mainnet \u2014 real funds at risk");
562
+ }
349
563
  const permissionManager = new PermissionManager(config.permissions);
350
564
  let frozen = false;
565
+ async function executeBatch(txs) {
566
+ for (const tx of txs) {
567
+ permissionManager.validate(tx);
568
+ }
569
+ try {
570
+ const userOpHash = await smartAccountClient.sendUserOperation({
571
+ calls: txs.map((tx) => ({
572
+ to: tx.to,
573
+ value: tx.value ?? 0n,
574
+ data: tx.data ?? "0x"
575
+ }))
576
+ });
577
+ const receipt = await smartAccountClient.waitForUserOperationReceipt({
578
+ hash: userOpHash
579
+ });
580
+ const totalValue = txs.reduce((sum, tx) => sum + (tx.value ?? 0n), 0n);
581
+ if (totalValue > 0n) permissionManager.recordSpend(totalValue);
582
+ return receipt.receipt.transactionHash;
583
+ } catch (error) {
584
+ throw humanizeError(error);
585
+ }
586
+ }
351
587
  const agent = {
352
588
  address: smartAccount.address,
353
589
  chain: config.chain,
@@ -375,26 +611,7 @@ async function createBarzAgent(config) {
375
611
  "BATCH_EMPTY"
376
612
  );
377
613
  }
378
- for (const tx of txs) {
379
- permissionManager.validate(tx);
380
- }
381
- try {
382
- const userOpHash = await smartAccountClient.sendUserOperation({
383
- calls: txs.map((tx) => ({
384
- to: tx.to,
385
- value: tx.value ?? 0n,
386
- data: tx.data ?? "0x"
387
- }))
388
- });
389
- const receipt = await smartAccountClient.waitForUserOperationReceipt({
390
- hash: userOpHash
391
- });
392
- const totalValue = txs.reduce((sum, tx) => sum + (tx.value ?? 0n), 0n);
393
- if (totalValue > 0n) permissionManager.recordSpend(totalValue);
394
- return receipt.receipt.transactionHash;
395
- } catch (error) {
396
- throw humanizeError(error);
397
- }
614
+ return executeBatch(txs);
398
615
  },
399
616
  async getBalance(token) {
400
617
  try {
@@ -428,6 +645,23 @@ async function createBarzAgent(config) {
428
645
  );
429
646
  }
430
647
  },
648
+ async swap(params) {
649
+ if (frozen) throw new FrozenError();
650
+ const tokenAddresses = getSwapTokenAddresses(params, config.chain);
651
+ validateTokenPermissions(tokenAddresses, permissionManager.permissions);
652
+ const txs = buildSwapTransactions(params, config.chain, smartAccount.address);
653
+ return executeBatch(txs);
654
+ },
655
+ async lend(params) {
656
+ if (frozen) throw new FrozenError();
657
+ const tokenAddresses = getLendTokenAddresses(params, config.chain);
658
+ validateTokenPermissions(tokenAddresses, permissionManager.permissions);
659
+ const txs = buildLendTransactions(params, config.chain, smartAccount.address);
660
+ return executeBatch(txs);
661
+ },
662
+ getExplorerUrl(hash) {
663
+ return `${chainConfig.explorerUrl}/tx/${hash}`;
664
+ },
431
665
  getPermissions() {
432
666
  return permissionManager.permissions;
433
667
  },
@@ -465,17 +699,38 @@ function validateConfig(config) {
465
699
  throw new ConfigError('Missing "pimlico.apiKey". Get a free key at https://dashboard.pimlico.io');
466
700
  }
467
701
  }
702
+ function validateTokenPermissions(tokenAddresses, permissions) {
703
+ if (!permissions.allowedTokens || permissions.allowedTokens.length === 0) return;
704
+ const allowed = permissions.allowedTokens.map((a) => a.toLowerCase());
705
+ for (const token of tokenAddresses) {
706
+ if (!allowed.includes(token.toLowerCase())) {
707
+ throw new PermissionError(
708
+ `Token ${token} is not in the allowed list. Allowed: ${permissions.allowedTokens.join(", ")}`
709
+ );
710
+ }
711
+ }
712
+ }
468
713
 
714
+ exports.AAVE_V3_POOL = AAVE_V3_POOL;
469
715
  exports.BarzKitError = BarzKitError;
470
716
  exports.BundlerError = BundlerError;
471
717
  exports.CHAIN_CONFIGS = CHAIN_CONFIGS;
472
718
  exports.ConfigError = ConfigError;
473
719
  exports.ERC20_ABI = ERC20_ABI;
720
+ exports.ETH_SENTINEL = ETH_SENTINEL;
474
721
  exports.FrozenError = FrozenError;
475
722
  exports.PermissionError = PermissionError;
476
723
  exports.TOKENS = TOKENS;
477
724
  exports.TransactionError = TransactionError;
725
+ exports.UNISWAP_V3_ROUTER = UNISWAP_V3_ROUTER;
726
+ exports.buildLendTransactions = buildLendTransactions;
727
+ exports.buildSwapTransactions = buildSwapTransactions;
478
728
  exports.createBarzAgent = createBarzAgent;
479
729
  exports.getChainConfig = getChainConfig;
730
+ exports.getLendTokenAddresses = getLendTokenAddresses;
731
+ exports.getSwapTokenAddresses = getSwapTokenAddresses;
732
+ exports.getTokenDecimals = getTokenDecimals;
733
+ exports.isNativeETH = isNativeETH;
734
+ exports.resolveToken = resolveToken;
480
735
  //# sourceMappingURL=index.cjs.map
481
736
  //# sourceMappingURL=index.cjs.map