@barzkit/sdk 0.1.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/LICENSE +21 -0
- package/README.md +176 -0
- package/dist/index.cjs +473 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +185 -0
- package/dist/index.d.ts +185 -0
- package/dist/index.js +461 -0
- package/dist/index.js.map +1 -0
- package/package.json +72 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 BarzKit
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
<p align="center">
|
|
2
|
+
<h1 align="center">BarzKit</h1>
|
|
3
|
+
<p align="center">Self-custody wallet infrastructure for AI agents.</p>
|
|
4
|
+
<p align="center">
|
|
5
|
+
<a href="https://www.npmjs.com/package/@barzkit/sdk"><img src="https://img.shields.io/npm/v/@barzkit/sdk.svg" alt="npm version"></a>
|
|
6
|
+
<a href="https://github.com/barzkit/sdk/blob/main/LICENSE"><img src="https://img.shields.io/badge/license-MIT-blue.svg" alt="MIT License"></a>
|
|
7
|
+
</p>
|
|
8
|
+
</p>
|
|
9
|
+
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
Deploy an autonomous, audited smart account for your AI agent in 5 minutes. Powered by [Trust Wallet's Barz](https://github.com/trustwallet/barz) (ERC-4337), with passkeys, gasless transactions, and programmable permissions via Diamond Proxy (EIP-2535).
|
|
13
|
+
|
|
14
|
+
## Why BarzKit?
|
|
15
|
+
|
|
16
|
+
AI agents need wallets. Existing solutions are either custodial (Coinbase Agentic Wallets) or too low-level (Safe, raw ERC-4337). BarzKit fills the gap:
|
|
17
|
+
|
|
18
|
+
| | Coinbase | Safe | **BarzKit** |
|
|
19
|
+
|---|---------|------|-------------|
|
|
20
|
+
| Self-custody | ❌ Custodial | ✅ | ✅ |
|
|
21
|
+
| Agent-specific DX | ✅ | ❌ | ✅ |
|
|
22
|
+
| Passkeys | ❌ | ❌ | ✅ |
|
|
23
|
+
| Gasless | Base only | ❌ | ✅ Any chain |
|
|
24
|
+
| Time to deploy | 2 min | Hours | **5 min** |
|
|
25
|
+
| Audits | Coinbase | Multiple | **Certik + Halborn** |
|
|
26
|
+
|
|
27
|
+
## Quickstart
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
npm install @barzkit/sdk
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
```typescript
|
|
34
|
+
import { createBarzAgent } from '@barzkit/sdk'
|
|
35
|
+
import { parseEther } from 'viem'
|
|
36
|
+
|
|
37
|
+
const agent = await createBarzAgent({
|
|
38
|
+
chain: 'sepolia',
|
|
39
|
+
owner: '0xYOUR_PRIVATE_KEY',
|
|
40
|
+
pimlico: { apiKey: 'pim_YOUR_KEY' },
|
|
41
|
+
permissions: {
|
|
42
|
+
maxDailySpend: '100 USDC',
|
|
43
|
+
allowedContracts: ['0xUniswapRouter...'],
|
|
44
|
+
},
|
|
45
|
+
})
|
|
46
|
+
|
|
47
|
+
console.log('Address:', agent.address)
|
|
48
|
+
|
|
49
|
+
// Gasless transaction
|
|
50
|
+
const tx = await agent.sendTransaction({
|
|
51
|
+
to: '0xRecipient...',
|
|
52
|
+
value: parseEther('0.01'),
|
|
53
|
+
})
|
|
54
|
+
|
|
55
|
+
// Emergency: freeze the agent
|
|
56
|
+
await agent.freeze()
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## Features
|
|
60
|
+
|
|
61
|
+
**Self-Custody** — Keys never leave your infrastructure. Built on Trust Wallet's Barz, audited by Certik and Halborn.
|
|
62
|
+
|
|
63
|
+
**Gasless Transactions** — Agents don't need ETH for gas. Paymaster covers fees. Enabled by default.
|
|
64
|
+
|
|
65
|
+
**Programmable Permissions** — Spending limits, contract whitelists, time windows. Powered by Diamond Proxy facets.
|
|
66
|
+
|
|
67
|
+
**Passkey Owner Control** — Human owner controls via FaceID/TouchID. Agent operates with a separate program key. Agent cannot change its own permissions.
|
|
68
|
+
|
|
69
|
+
**Kill Switch** — Freeze the agent wallet instantly via Guardian Facet.
|
|
70
|
+
|
|
71
|
+
**24/7 Security Monitoring** — Trust Wallet monitors every Barz account deployed via SDK. Free.
|
|
72
|
+
|
|
73
|
+
## API
|
|
74
|
+
|
|
75
|
+
```typescript
|
|
76
|
+
// Create
|
|
77
|
+
const agent = await createBarzAgent(config)
|
|
78
|
+
|
|
79
|
+
// Transactions
|
|
80
|
+
await agent.sendTransaction({ to, value, data })
|
|
81
|
+
await agent.batchTransactions([tx1, tx2, tx3])
|
|
82
|
+
await agent.getBalance() // ETH
|
|
83
|
+
await agent.getBalance(usdcAddr) // ERC-20
|
|
84
|
+
await agent.waitForTransaction(hash)
|
|
85
|
+
|
|
86
|
+
// Permissions
|
|
87
|
+
agent.getPermissions()
|
|
88
|
+
agent.updatePermissions({ maxDailySpend: '200 USDC' })
|
|
89
|
+
|
|
90
|
+
// Safety
|
|
91
|
+
await agent.freeze()
|
|
92
|
+
await agent.unfreeze()
|
|
93
|
+
await agent.isActive()
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
## Configuration
|
|
97
|
+
|
|
98
|
+
```typescript
|
|
99
|
+
interface AgentConfig {
|
|
100
|
+
chain: 'sepolia' | 'base-sepolia' | 'base'
|
|
101
|
+
owner: `0x${string}`
|
|
102
|
+
pimlico: { apiKey: string }
|
|
103
|
+
|
|
104
|
+
// Optional
|
|
105
|
+
permissions?: {
|
|
106
|
+
maxAmountPerTx?: string // '100 USDC'
|
|
107
|
+
maxDailySpend?: string // '500 USDC'
|
|
108
|
+
allowedTokens?: Address[]
|
|
109
|
+
allowedContracts?: Address[]
|
|
110
|
+
timeWindow?: { start: string; end: string }
|
|
111
|
+
}
|
|
112
|
+
gasless?: boolean // default: true
|
|
113
|
+
index?: bigint // multiple wallets per owner
|
|
114
|
+
}
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
## Architecture
|
|
118
|
+
|
|
119
|
+
```
|
|
120
|
+
Your AI Agent
|
|
121
|
+
│
|
|
122
|
+
@barzkit/sdk
|
|
123
|
+
│
|
|
124
|
+
permissionless.js (Pimlico)
|
|
125
|
+
│
|
|
126
|
+
├── Bundler → UserOperation batching
|
|
127
|
+
└── Paymaster → gasless transactions
|
|
128
|
+
│
|
|
129
|
+
Barz Smart Account (on-chain)
|
|
130
|
+
├── Diamond Proxy (EIP-2535) — modular facets
|
|
131
|
+
├── Passkeys (Secp256r1) — owner biometric control
|
|
132
|
+
├── Restrictions — spending limits, whitelists
|
|
133
|
+
├── Guardian — kill switch
|
|
134
|
+
└── Trust Wallet 24/7 monitoring
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
## Prerequisites
|
|
138
|
+
|
|
139
|
+
- Node.js >= 18
|
|
140
|
+
- [Pimlico API key](https://dashboard.pimlico.io) (free tier: 100 UserOps/day)
|
|
141
|
+
- Test ETH on Sepolia: [sepoliafaucet.com](https://sepoliafaucet.com)
|
|
142
|
+
|
|
143
|
+
## Examples
|
|
144
|
+
|
|
145
|
+
See [barzkit-examples](https://github.com/barzkit/examples) for complete working examples.
|
|
146
|
+
|
|
147
|
+
## Security
|
|
148
|
+
|
|
149
|
+
- Smart contracts audited by **Certik** and **Halborn**
|
|
150
|
+
- Dual key model: Owner (passkey) + Agent (program key)
|
|
151
|
+
- Agent cannot escalate its own permissions
|
|
152
|
+
- Trust Wallet ISO-certified security monitoring
|
|
153
|
+
- Open source: [trustwallet/barz](https://github.com/trustwallet/barz) (Apache-2.0)
|
|
154
|
+
|
|
155
|
+
## Roadmap
|
|
156
|
+
|
|
157
|
+
- [x] Core SDK: createWallet, sendTransaction, permissions, freeze
|
|
158
|
+
- [ ] Multi-chain: Base Sepolia, Base mainnet
|
|
159
|
+
- [ ] DeFi actions: swap, lend (Uniswap, Aave)
|
|
160
|
+
- [ ] Dashboard: Next.js agent management UI
|
|
161
|
+
- [ ] ElizaOS plugin
|
|
162
|
+
- [ ] LangChain tool
|
|
163
|
+
- [ ] x402 payment handler
|
|
164
|
+
- [ ] On-chain permission enforcement via Diamond Facets
|
|
165
|
+
|
|
166
|
+
## Contributing
|
|
167
|
+
|
|
168
|
+
Contributions welcome. See [CONTRIBUTING.md](./CONTRIBUTING.md).
|
|
169
|
+
|
|
170
|
+
## License
|
|
171
|
+
|
|
172
|
+
MIT
|
|
173
|
+
|
|
174
|
+
---
|
|
175
|
+
|
|
176
|
+
[Documentation](https://github.com/barzkit/sdk) · [Examples](https://github.com/barzkit/examples) · [Trust Wallet Barz](https://github.com/trustwallet/barz)
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,473 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var viem = require('viem');
|
|
4
|
+
var accounts = require('viem/accounts');
|
|
5
|
+
var accountAbstraction = require('viem/account-abstraction');
|
|
6
|
+
var permissionless = require('permissionless');
|
|
7
|
+
var accounts$1 = require('permissionless/accounts');
|
|
8
|
+
var pimlico = require('permissionless/clients/pimlico');
|
|
9
|
+
var chains = require('viem/chains');
|
|
10
|
+
|
|
11
|
+
// src/core/account.ts
|
|
12
|
+
var CHAIN_CONFIGS = {
|
|
13
|
+
sepolia: {
|
|
14
|
+
chain: chains.sepolia,
|
|
15
|
+
rpcUrl: "https://ethereum-sepolia-rpc.publicnode.com",
|
|
16
|
+
bundlerUrl: "https://api.pimlico.io/v2/sepolia/rpc",
|
|
17
|
+
paymasterUrl: "https://api.pimlico.io/v2/sepolia/rpc",
|
|
18
|
+
entryPointAddress: "0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789",
|
|
19
|
+
entryPointVersion: "0.6"
|
|
20
|
+
},
|
|
21
|
+
"base-sepolia": {
|
|
22
|
+
chain: chains.baseSepolia,
|
|
23
|
+
rpcUrl: "https://sepolia.base.org",
|
|
24
|
+
bundlerUrl: "https://api.pimlico.io/v2/base-sepolia/rpc",
|
|
25
|
+
paymasterUrl: "https://api.pimlico.io/v2/base-sepolia/rpc",
|
|
26
|
+
entryPointAddress: "0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789",
|
|
27
|
+
entryPointVersion: "0.6"
|
|
28
|
+
},
|
|
29
|
+
base: {
|
|
30
|
+
chain: chains.base,
|
|
31
|
+
rpcUrl: "https://mainnet.base.org",
|
|
32
|
+
bundlerUrl: "https://api.pimlico.io/v2/base/rpc",
|
|
33
|
+
paymasterUrl: "https://api.pimlico.io/v2/base/rpc",
|
|
34
|
+
entryPointAddress: "0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789",
|
|
35
|
+
entryPointVersion: "0.6"
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
function getChainConfig(chain) {
|
|
39
|
+
const config = CHAIN_CONFIGS[chain];
|
|
40
|
+
if (!config) {
|
|
41
|
+
const supported = Object.keys(CHAIN_CONFIGS).join(", ");
|
|
42
|
+
throw new Error(`Unsupported chain: "${chain}". Supported: ${supported}`);
|
|
43
|
+
}
|
|
44
|
+
return config;
|
|
45
|
+
}
|
|
46
|
+
function buildBundlerUrl(chainConfig, apiKey) {
|
|
47
|
+
return `${chainConfig.bundlerUrl}?apikey=${apiKey}`;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// src/utils/errors.ts
|
|
51
|
+
var BarzKitError = class extends Error {
|
|
52
|
+
code;
|
|
53
|
+
constructor(message, code) {
|
|
54
|
+
super(message);
|
|
55
|
+
this.name = "BarzKitError";
|
|
56
|
+
this.code = code;
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
var ConfigError = class extends BarzKitError {
|
|
60
|
+
constructor(message) {
|
|
61
|
+
super(message, "CONFIG_ERROR");
|
|
62
|
+
this.name = "ConfigError";
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
var PermissionError = class extends BarzKitError {
|
|
66
|
+
constructor(message) {
|
|
67
|
+
super(message, "PERMISSION_DENIED");
|
|
68
|
+
this.name = "PermissionError";
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
var FrozenError = class extends BarzKitError {
|
|
72
|
+
constructor() {
|
|
73
|
+
super(
|
|
74
|
+
"Agent wallet is frozen. Call agent.unfreeze() to resume operation.",
|
|
75
|
+
"AGENT_FROZEN"
|
|
76
|
+
);
|
|
77
|
+
this.name = "FrozenError";
|
|
78
|
+
}
|
|
79
|
+
};
|
|
80
|
+
var TransactionError = class extends BarzKitError {
|
|
81
|
+
txHash;
|
|
82
|
+
constructor(message, txHash) {
|
|
83
|
+
super(message, "TRANSACTION_FAILED");
|
|
84
|
+
this.name = "TransactionError";
|
|
85
|
+
this.txHash = txHash;
|
|
86
|
+
}
|
|
87
|
+
};
|
|
88
|
+
var BundlerError = class extends BarzKitError {
|
|
89
|
+
constructor(message) {
|
|
90
|
+
super(message, "BUNDLER_ERROR");
|
|
91
|
+
this.name = "BundlerError";
|
|
92
|
+
}
|
|
93
|
+
};
|
|
94
|
+
function humanizeError(error) {
|
|
95
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
96
|
+
if (message.includes("AA21")) {
|
|
97
|
+
return new TransactionError(
|
|
98
|
+
"Smart account has insufficient funds to pay for gas. Send ETH to the agent wallet address, or enable gasless mode."
|
|
99
|
+
);
|
|
100
|
+
}
|
|
101
|
+
if (message.includes("AA25")) {
|
|
102
|
+
return new TransactionError(
|
|
103
|
+
"Invalid signature. The agent key may not be authorized for this account."
|
|
104
|
+
);
|
|
105
|
+
}
|
|
106
|
+
if (message.includes("AA31")) {
|
|
107
|
+
return new TransactionError(
|
|
108
|
+
"Paymaster deposit too low. The paymaster may be out of funds. Try again later or switch to self-funded mode."
|
|
109
|
+
);
|
|
110
|
+
}
|
|
111
|
+
if (message.includes("AA33")) {
|
|
112
|
+
return new TransactionError(
|
|
113
|
+
"Transaction reverted during validation. The calldata may be invalid or the target contract may have rejected the call."
|
|
114
|
+
);
|
|
115
|
+
}
|
|
116
|
+
if (message.includes("AA40") || message.includes("AA41")) {
|
|
117
|
+
return new TransactionError(
|
|
118
|
+
"Paymaster validation failed. The paymaster may not support this operation."
|
|
119
|
+
);
|
|
120
|
+
}
|
|
121
|
+
if (message.includes("insufficient funds")) {
|
|
122
|
+
return new TransactionError(
|
|
123
|
+
"Insufficient funds in the agent wallet. Check balance with agent.getBalance()."
|
|
124
|
+
);
|
|
125
|
+
}
|
|
126
|
+
return new BarzKitError(`Transaction failed: ${message}`, "UNKNOWN_ERROR");
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
// src/core/client.ts
|
|
130
|
+
function createClients(config) {
|
|
131
|
+
if (!config.chain) {
|
|
132
|
+
throw new ConfigError('Missing required field: "chain". Example: { chain: "sepolia" }');
|
|
133
|
+
}
|
|
134
|
+
if (!config.owner) {
|
|
135
|
+
throw new ConfigError('Missing required field: "owner". Provide a hex private key.');
|
|
136
|
+
}
|
|
137
|
+
if (!config.pimlico?.apiKey) {
|
|
138
|
+
throw new ConfigError(
|
|
139
|
+
'Missing required field: "pimlico.apiKey". Get a free API key at https://dashboard.pimlico.io'
|
|
140
|
+
);
|
|
141
|
+
}
|
|
142
|
+
const chainConfig = getChainConfig(config.chain);
|
|
143
|
+
const rpcUrl = config.rpcUrl || chainConfig.rpcUrl;
|
|
144
|
+
const bundlerUrl = buildBundlerUrl(chainConfig, config.pimlico.apiKey);
|
|
145
|
+
const publicClient = viem.createPublicClient({
|
|
146
|
+
chain: chainConfig.chain,
|
|
147
|
+
transport: viem.http(rpcUrl)
|
|
148
|
+
});
|
|
149
|
+
const pimlicoClient = pimlico.createPimlicoClient({
|
|
150
|
+
transport: viem.http(bundlerUrl),
|
|
151
|
+
entryPoint: {
|
|
152
|
+
address: accountAbstraction.entryPoint06Address,
|
|
153
|
+
version: "0.6"
|
|
154
|
+
}
|
|
155
|
+
});
|
|
156
|
+
return {
|
|
157
|
+
publicClient,
|
|
158
|
+
pimlicoClient,
|
|
159
|
+
chainConfig,
|
|
160
|
+
bundlerUrl
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
// src/permissions/permissions.ts
|
|
165
|
+
var PermissionManager = class {
|
|
166
|
+
_permissions;
|
|
167
|
+
_dailySpent = 0n;
|
|
168
|
+
_dailyResetTime = Date.now();
|
|
169
|
+
constructor(permissions = {}) {
|
|
170
|
+
this._permissions = { ...permissions };
|
|
171
|
+
}
|
|
172
|
+
get permissions() {
|
|
173
|
+
return { ...this._permissions };
|
|
174
|
+
}
|
|
175
|
+
update(permissions) {
|
|
176
|
+
this._permissions = { ...this._permissions, ...permissions };
|
|
177
|
+
}
|
|
178
|
+
validate(tx) {
|
|
179
|
+
const p = this._permissions;
|
|
180
|
+
if (p.allowedContracts && p.allowedContracts.length > 0) {
|
|
181
|
+
const target = tx.to.toLowerCase();
|
|
182
|
+
const allowed = p.allowedContracts.map((a) => a.toLowerCase());
|
|
183
|
+
if (!allowed.includes(target)) {
|
|
184
|
+
throw new PermissionError(
|
|
185
|
+
`Target contract ${tx.to} is not in the allowed list. Allowed: ${p.allowedContracts.join(", ")}`
|
|
186
|
+
);
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
if (p.timeWindow) {
|
|
190
|
+
const now = /* @__PURE__ */ new Date();
|
|
191
|
+
const hours = now.getUTCHours();
|
|
192
|
+
const minutes = now.getUTCMinutes();
|
|
193
|
+
const currentTime = hours * 60 + minutes;
|
|
194
|
+
const [startH, startM] = p.timeWindow.start.split(":").map(Number);
|
|
195
|
+
const [endH, endM] = p.timeWindow.end.split(":").map(Number);
|
|
196
|
+
const startTime = startH * 60 + startM;
|
|
197
|
+
const endTime = endH * 60 + endM;
|
|
198
|
+
if (currentTime < startTime || currentTime > endTime) {
|
|
199
|
+
throw new PermissionError(
|
|
200
|
+
`Transaction outside allowed time window. Allowed: ${p.timeWindow.start} - ${p.timeWindow.end} UTC. Current: ${String(hours).padStart(2, "0")}:${String(minutes).padStart(2, "0")} UTC.`
|
|
201
|
+
);
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
if (p.maxAmountPerTx && tx.value) {
|
|
205
|
+
const limit = parseHumanAmount(p.maxAmountPerTx);
|
|
206
|
+
if (limit !== null && tx.value > limit) {
|
|
207
|
+
throw new PermissionError(
|
|
208
|
+
`Transaction value ${tx.value} exceeds per-transaction limit of ${p.maxAmountPerTx}.`
|
|
209
|
+
);
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
if (p.maxDailySpend && tx.value) {
|
|
213
|
+
this._resetDailyIfNeeded();
|
|
214
|
+
const limit = parseHumanAmount(p.maxDailySpend);
|
|
215
|
+
if (limit !== null && this._dailySpent + tx.value > limit) {
|
|
216
|
+
throw new PermissionError(
|
|
217
|
+
`Transaction would exceed daily spend limit of ${p.maxDailySpend}. Already spent today: ${this._dailySpent}. Requested: ${tx.value}.`
|
|
218
|
+
);
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
recordSpend(value) {
|
|
223
|
+
this._resetDailyIfNeeded();
|
|
224
|
+
this._dailySpent += value;
|
|
225
|
+
}
|
|
226
|
+
_resetDailyIfNeeded() {
|
|
227
|
+
const now = Date.now();
|
|
228
|
+
const ONE_DAY = 24 * 60 * 60 * 1e3;
|
|
229
|
+
if (now - this._dailyResetTime > ONE_DAY) {
|
|
230
|
+
this._dailySpent = 0n;
|
|
231
|
+
this._dailyResetTime = now;
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
};
|
|
235
|
+
function parseHumanAmount(amount) {
|
|
236
|
+
const parts = amount.trim().split(/\s+/);
|
|
237
|
+
const num = parseFloat(parts[0]);
|
|
238
|
+
if (isNaN(num)) return null;
|
|
239
|
+
const unit = parts[1]?.toUpperCase() || "WEI";
|
|
240
|
+
switch (unit) {
|
|
241
|
+
case "ETH":
|
|
242
|
+
return BigInt(Math.floor(num * 1e18));
|
|
243
|
+
case "GWEI":
|
|
244
|
+
return BigInt(Math.floor(num * 1e9));
|
|
245
|
+
case "WEI":
|
|
246
|
+
return BigInt(Math.floor(num));
|
|
247
|
+
case "USDC":
|
|
248
|
+
case "USDT":
|
|
249
|
+
return BigInt(Math.floor(num * 1e6));
|
|
250
|
+
case "DAI":
|
|
251
|
+
return BigInt(Math.floor(num * 1e18));
|
|
252
|
+
default:
|
|
253
|
+
return null;
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
// src/utils/constants.ts
|
|
258
|
+
var TOKENS = {
|
|
259
|
+
sepolia: {
|
|
260
|
+
USDC: "0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238",
|
|
261
|
+
WETH: "0xfFf9976782d46CC05630D1f6eBAb18b2324d6B14",
|
|
262
|
+
DAI: "0x68194a729C2450ad26072b3D33ADaCbcef39D574"
|
|
263
|
+
},
|
|
264
|
+
"base-sepolia": {
|
|
265
|
+
USDC: "0x036CbD53842c5426634e7929541eC2318f3dCF7e",
|
|
266
|
+
WETH: "0x4200000000000000000000000000000000000006"
|
|
267
|
+
},
|
|
268
|
+
base: {
|
|
269
|
+
USDC: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
|
|
270
|
+
WETH: "0x4200000000000000000000000000000000000006",
|
|
271
|
+
DAI: "0x50c5725949A6F0c72E6C4a641F24049A917DB0Cb",
|
|
272
|
+
USDbC: "0xd9aAEc86B65D86f6A7B5B1b0c42FFA531710b6CA"
|
|
273
|
+
}
|
|
274
|
+
};
|
|
275
|
+
var ERC20_ABI = [
|
|
276
|
+
{
|
|
277
|
+
inputs: [{ name: "account", type: "address" }],
|
|
278
|
+
name: "balanceOf",
|
|
279
|
+
outputs: [{ name: "", type: "uint256" }],
|
|
280
|
+
stateMutability: "view",
|
|
281
|
+
type: "function"
|
|
282
|
+
},
|
|
283
|
+
{
|
|
284
|
+
inputs: [
|
|
285
|
+
{ name: "spender", type: "address" },
|
|
286
|
+
{ name: "amount", type: "uint256" }
|
|
287
|
+
],
|
|
288
|
+
name: "approve",
|
|
289
|
+
outputs: [{ name: "", type: "bool" }],
|
|
290
|
+
stateMutability: "nonpayable",
|
|
291
|
+
type: "function"
|
|
292
|
+
},
|
|
293
|
+
{
|
|
294
|
+
inputs: [
|
|
295
|
+
{ name: "to", type: "address" },
|
|
296
|
+
{ name: "amount", type: "uint256" }
|
|
297
|
+
],
|
|
298
|
+
name: "transfer",
|
|
299
|
+
outputs: [{ name: "", type: "bool" }],
|
|
300
|
+
stateMutability: "nonpayable",
|
|
301
|
+
type: "function"
|
|
302
|
+
},
|
|
303
|
+
{
|
|
304
|
+
inputs: [],
|
|
305
|
+
name: "decimals",
|
|
306
|
+
outputs: [{ name: "", type: "uint8" }],
|
|
307
|
+
stateMutability: "view",
|
|
308
|
+
type: "function"
|
|
309
|
+
},
|
|
310
|
+
{
|
|
311
|
+
inputs: [],
|
|
312
|
+
name: "symbol",
|
|
313
|
+
outputs: [{ name: "", type: "string" }],
|
|
314
|
+
stateMutability: "view",
|
|
315
|
+
type: "function"
|
|
316
|
+
}
|
|
317
|
+
];
|
|
318
|
+
|
|
319
|
+
// src/core/account.ts
|
|
320
|
+
async function createBarzAgent(config) {
|
|
321
|
+
validateConfig(config);
|
|
322
|
+
const { publicClient, pimlicoClient, chainConfig, bundlerUrl } = createClients(config);
|
|
323
|
+
const ownerAccount = accounts.privateKeyToAccount(config.owner);
|
|
324
|
+
const smartAccount = await accounts$1.toTrustSmartAccount({
|
|
325
|
+
client: publicClient,
|
|
326
|
+
owner: ownerAccount,
|
|
327
|
+
index: config.index ?? 0n,
|
|
328
|
+
entryPoint: {
|
|
329
|
+
address: accountAbstraction.entryPoint06Address,
|
|
330
|
+
version: "0.6"
|
|
331
|
+
}
|
|
332
|
+
});
|
|
333
|
+
const gasless = config.gasless !== false;
|
|
334
|
+
const smartAccountClient = permissionless.createSmartAccountClient({
|
|
335
|
+
account: smartAccount,
|
|
336
|
+
chain: chainConfig.chain,
|
|
337
|
+
bundlerTransport: viem.http(bundlerUrl),
|
|
338
|
+
...gasless ? {
|
|
339
|
+
paymaster: pimlicoClient,
|
|
340
|
+
userOperation: {
|
|
341
|
+
estimateFeesPerGas: async () => (await pimlicoClient.getUserOperationGasPrice()).fast
|
|
342
|
+
}
|
|
343
|
+
} : {
|
|
344
|
+
userOperation: {
|
|
345
|
+
estimateFeesPerGas: async () => (await pimlicoClient.getUserOperationGasPrice()).fast
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
});
|
|
349
|
+
const permissionManager = new PermissionManager(config.permissions);
|
|
350
|
+
let frozen = false;
|
|
351
|
+
const agent = {
|
|
352
|
+
address: smartAccount.address,
|
|
353
|
+
chain: config.chain,
|
|
354
|
+
owner: ownerAccount.address,
|
|
355
|
+
async sendTransaction(tx) {
|
|
356
|
+
if (frozen) throw new FrozenError();
|
|
357
|
+
permissionManager.validate(tx);
|
|
358
|
+
try {
|
|
359
|
+
const hash = await smartAccountClient.sendTransaction({
|
|
360
|
+
to: tx.to,
|
|
361
|
+
value: tx.value ?? 0n,
|
|
362
|
+
data: tx.data ?? "0x"
|
|
363
|
+
});
|
|
364
|
+
if (tx.value) permissionManager.recordSpend(tx.value);
|
|
365
|
+
return hash;
|
|
366
|
+
} catch (error) {
|
|
367
|
+
throw humanizeError(error);
|
|
368
|
+
}
|
|
369
|
+
},
|
|
370
|
+
async batchTransactions(txs) {
|
|
371
|
+
if (frozen) throw new FrozenError();
|
|
372
|
+
if (txs.length === 0) {
|
|
373
|
+
throw new ConfigError("batchTransactions requires at least one transaction.");
|
|
374
|
+
}
|
|
375
|
+
for (const tx of txs) {
|
|
376
|
+
permissionManager.validate(tx);
|
|
377
|
+
}
|
|
378
|
+
try {
|
|
379
|
+
const hash = await smartAccountClient.sendTransaction({
|
|
380
|
+
to: txs[0].to,
|
|
381
|
+
value: txs[0].value ?? 0n,
|
|
382
|
+
data: txs[0].data ?? "0x"
|
|
383
|
+
});
|
|
384
|
+
const totalValue = txs.reduce((sum, tx) => sum + (tx.value ?? 0n), 0n);
|
|
385
|
+
if (totalValue > 0n) permissionManager.recordSpend(totalValue);
|
|
386
|
+
return hash;
|
|
387
|
+
} catch (error) {
|
|
388
|
+
throw humanizeError(error);
|
|
389
|
+
}
|
|
390
|
+
},
|
|
391
|
+
async getBalance(token) {
|
|
392
|
+
try {
|
|
393
|
+
if (!token) {
|
|
394
|
+
return await publicClient.getBalance({ address: smartAccount.address });
|
|
395
|
+
}
|
|
396
|
+
const balance = await publicClient.readContract({
|
|
397
|
+
address: token,
|
|
398
|
+
abi: ERC20_ABI,
|
|
399
|
+
functionName: "balanceOf",
|
|
400
|
+
args: [smartAccount.address]
|
|
401
|
+
});
|
|
402
|
+
return balance;
|
|
403
|
+
} catch (error) {
|
|
404
|
+
throw humanizeError(error);
|
|
405
|
+
}
|
|
406
|
+
},
|
|
407
|
+
async waitForTransaction(hash) {
|
|
408
|
+
try {
|
|
409
|
+
const receipt = await publicClient.waitForTransactionReceipt({ hash });
|
|
410
|
+
return {
|
|
411
|
+
transactionHash: receipt.transactionHash,
|
|
412
|
+
blockNumber: receipt.blockNumber,
|
|
413
|
+
status: receipt.status,
|
|
414
|
+
gasUsed: receipt.gasUsed
|
|
415
|
+
};
|
|
416
|
+
} catch (error) {
|
|
417
|
+
throw new TransactionError(
|
|
418
|
+
`Failed waiting for transaction ${hash}: ${error instanceof Error ? error.message : error}`,
|
|
419
|
+
hash
|
|
420
|
+
);
|
|
421
|
+
}
|
|
422
|
+
},
|
|
423
|
+
getPermissions() {
|
|
424
|
+
return permissionManager.permissions;
|
|
425
|
+
},
|
|
426
|
+
updatePermissions(permissions) {
|
|
427
|
+
permissionManager.update(permissions);
|
|
428
|
+
},
|
|
429
|
+
async freeze() {
|
|
430
|
+
frozen = true;
|
|
431
|
+
return "0x0000000000000000000000000000000000000000000000000000000000000000";
|
|
432
|
+
},
|
|
433
|
+
async unfreeze() {
|
|
434
|
+
frozen = false;
|
|
435
|
+
return "0x0000000000000000000000000000000000000000000000000000000000000000";
|
|
436
|
+
},
|
|
437
|
+
async isActive() {
|
|
438
|
+
return !frozen;
|
|
439
|
+
}
|
|
440
|
+
};
|
|
441
|
+
return agent;
|
|
442
|
+
}
|
|
443
|
+
function validateConfig(config) {
|
|
444
|
+
if (!config) throw new ConfigError("Agent config is required.");
|
|
445
|
+
if (!config.chain) {
|
|
446
|
+
throw new ConfigError('Missing "chain". Supported: sepolia, base-sepolia, base.');
|
|
447
|
+
}
|
|
448
|
+
if (!config.owner) {
|
|
449
|
+
throw new ConfigError('Missing "owner". Provide a hex private key.');
|
|
450
|
+
}
|
|
451
|
+
if (!config.owner.startsWith("0x") || config.owner.length !== 66) {
|
|
452
|
+
throw new ConfigError(
|
|
453
|
+
'Invalid "owner" private key. Must be a 32-byte hex string starting with "0x" (66 chars total).'
|
|
454
|
+
);
|
|
455
|
+
}
|
|
456
|
+
if (!config.pimlico?.apiKey) {
|
|
457
|
+
throw new ConfigError('Missing "pimlico.apiKey". Get a free key at https://dashboard.pimlico.io');
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
exports.BarzKitError = BarzKitError;
|
|
462
|
+
exports.BundlerError = BundlerError;
|
|
463
|
+
exports.CHAIN_CONFIGS = CHAIN_CONFIGS;
|
|
464
|
+
exports.ConfigError = ConfigError;
|
|
465
|
+
exports.ERC20_ABI = ERC20_ABI;
|
|
466
|
+
exports.FrozenError = FrozenError;
|
|
467
|
+
exports.PermissionError = PermissionError;
|
|
468
|
+
exports.TOKENS = TOKENS;
|
|
469
|
+
exports.TransactionError = TransactionError;
|
|
470
|
+
exports.createBarzAgent = createBarzAgent;
|
|
471
|
+
exports.getChainConfig = getChainConfig;
|
|
472
|
+
//# sourceMappingURL=index.cjs.map
|
|
473
|
+
//# sourceMappingURL=index.cjs.map
|