clawpowers 1.1.2 → 1.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/README.md +197 -313
- package/bin/clawpowers.js +29 -13
- package/docs/quickstart-first-transaction.md +204 -0
- package/package.json +7 -3
- package/runtime/demo/README.md +78 -0
- package/runtime/demo/x402-mock-server.js +1 -1
- package/runtime/init.sh +1 -1
- package/runtime/payments/pipeline.js +455 -0
- package/skill.json +26 -5
- package/skills/agent-bounties/SKILL.md +553 -0
- package/skills/prospecting/SKILL.md +141 -0
- package/skills/using-clawpowers/SKILL.md +6 -1
- package/skills/validator/SKILL.md +281 -0
package/bin/clawpowers.js
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
const fs = require('fs');
|
|
10
10
|
const path = require('path');
|
|
11
11
|
const os = require('os');
|
|
12
|
-
const {
|
|
12
|
+
const { spawnSync } = require('child_process');
|
|
13
13
|
|
|
14
14
|
// __dirname is the bin/ directory; repo root is one level up
|
|
15
15
|
const SCRIPT_DIR = __dirname;
|
|
@@ -107,19 +107,35 @@ function cmdStatus() {
|
|
|
107
107
|
*/
|
|
108
108
|
function cmdUpdate() {
|
|
109
109
|
const repoUrl = 'https://github.com/up2itnow0822/clawpowers';
|
|
110
|
-
const result = spawnSync('git', ['-C', REPO_ROOT, 'pull', '--ff-only', 'origin', 'main'], {
|
|
111
|
-
stdio: 'inherit',
|
|
112
|
-
// On Windows, git must be launched through the shell so PATH is resolved
|
|
113
|
-
shell: os.platform() === 'win32',
|
|
114
|
-
});
|
|
115
110
|
|
|
116
|
-
if (
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
111
|
+
// Check if we're in a git repo (git clone install) or npm install
|
|
112
|
+
const gitDir = path.join(REPO_ROOT, '.git');
|
|
113
|
+
const isGitInstall = fs.existsSync(gitDir);
|
|
114
|
+
|
|
115
|
+
if (isGitInstall) {
|
|
116
|
+
// Git install: pull latest
|
|
117
|
+
const result = spawnSync('git', ['-C', REPO_ROOT, 'pull', '--ff-only', 'origin', 'main'], {
|
|
118
|
+
stdio: 'inherit',
|
|
119
|
+
shell: os.platform() === 'win32',
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
if (result.error) {
|
|
123
|
+
console.log(`git not found or failed. Visit ${repoUrl} to update manually.`);
|
|
124
|
+
} else if (result.status !== 0) {
|
|
125
|
+
console.log(`Warning: could not auto-update. Visit ${repoUrl} for latest.`);
|
|
126
|
+
} else {
|
|
127
|
+
console.log('Updated to latest version.');
|
|
128
|
+
}
|
|
121
129
|
} else {
|
|
122
|
-
|
|
130
|
+
// npm/npx install: instruct user to reinstall via npm
|
|
131
|
+
console.log('ClawPowers was installed via npm. To update:');
|
|
132
|
+
console.log('');
|
|
133
|
+
console.log(' npx clawpowers@latest init');
|
|
134
|
+
console.log('');
|
|
135
|
+
console.log('This will update the CLI and re-initialize the runtime');
|
|
136
|
+
console.log('(your existing state, metrics, and config are preserved).');
|
|
137
|
+
console.log('');
|
|
138
|
+
console.log(`Or visit: ${repoUrl}`);
|
|
123
139
|
}
|
|
124
140
|
}
|
|
125
141
|
|
|
@@ -146,7 +162,7 @@ function cmdInject() {
|
|
|
146
162
|
* @param {string[]} args - Remaining argv after 'metrics'.
|
|
147
163
|
*/
|
|
148
164
|
function cmdMetrics(args) {
|
|
149
|
-
const
|
|
165
|
+
const _collector = requireModule(COLLECTOR_JS);
|
|
150
166
|
const [subcmd, ...rest] = args;
|
|
151
167
|
|
|
152
168
|
// No subcommand or explicit help request: print metrics-specific usage
|
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
# 5-Minute First Transaction
|
|
2
|
+
|
|
3
|
+
Get your AI agent sending real (testnet) transactions in under 5 minutes.
|
|
4
|
+
Two paths — pick the one that matches your stack.
|
|
5
|
+
|
|
6
|
+
> **Testnet only.** Both paths use **Base Sepolia** so no real money moves.
|
|
7
|
+
> Switch `CHAIN_NAME=base` when you're ready for mainnet.
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## Prerequisites
|
|
12
|
+
|
|
13
|
+
1. **Testnet wallet** — any EOA private key (generate one with `cast wallet new` from Foundry, or MetaMask)
|
|
14
|
+
2. **Deployed AgentAccountV2** — run `npx clawpowers payments setup` for the interactive wizard
|
|
15
|
+
3. **Base Sepolia ETH (gas)** — free from the [Coinbase Base Sepolia Faucet](https://www.coinbase.com/faucets/base-ethereum-goerli-faucet)
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
## .env Setup
|
|
20
|
+
|
|
21
|
+
Create a `.env` file (never commit this):
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
# .env — agent wallet config
|
|
25
|
+
AGENT_PRIVATE_KEY=0x... # EOA signing key (32-byte hex)
|
|
26
|
+
AGENT_WALLET_ADDRESS=0x... # AgentAccountV2 contract address
|
|
27
|
+
CHAIN_NAME=base-sepolia # Use Base Sepolia for testing
|
|
28
|
+
RPC_URL=https://sepolia.base.org
|
|
29
|
+
|
|
30
|
+
# Spending limits (USDC, 6 decimals)
|
|
31
|
+
SPEND_LIMIT_PER_TX=1.00 # Max USDC per single transaction
|
|
32
|
+
SPEND_LIMIT_DAILY=10.00 # Max USDC per 24-hour period
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
---
|
|
36
|
+
|
|
37
|
+
## Path A: JavaScript (agentwallet-sdk direct)
|
|
38
|
+
|
|
39
|
+
**Under 10 lines.** Uses the `walletFromEnv()` convenience wrapper so there's
|
|
40
|
+
no viem boilerplate.
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
npm install agentwallet-sdk dotenv
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
```javascript
|
|
47
|
+
// first-tx.mjs
|
|
48
|
+
import 'dotenv/config';
|
|
49
|
+
import { walletFromEnv, setPolicyFromEnv, agentExecute } from 'agentwallet-sdk';
|
|
50
|
+
|
|
51
|
+
const wallet = await walletFromEnv(); // reads AGENT_PRIVATE_KEY + AGENT_WALLET_ADDRESS
|
|
52
|
+
await setPolicyFromEnv(wallet); // applies SPEND_LIMIT_PER_TX + SPEND_LIMIT_DAILY
|
|
53
|
+
|
|
54
|
+
const result = await agentExecute(wallet, {
|
|
55
|
+
to: '0x000000000000000000000000000000000000dEaD', // burn address (safe test target)
|
|
56
|
+
value: 1n, // 1 wei — near-zero cost
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
console.log(`✅ txHash: ${result.txHash}`);
|
|
60
|
+
console.log(` executed immediately: ${result.executed}`);
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
node first-tx.mjs
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
**Expected output:**
|
|
68
|
+
```
|
|
69
|
+
✅ txHash: 0x3a7f...c9e2
|
|
70
|
+
executed immediately: true
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
> If `executed: false` — the transaction was queued for owner approval because
|
|
74
|
+
> the amount exceeded your spend policy. Approve it with:
|
|
75
|
+
> ```bash
|
|
76
|
+
> node -e "
|
|
77
|
+
> import('agentwallet-sdk').then(async ({ walletFromEnv, getPendingApprovals, approveTransaction }) => {
|
|
78
|
+
> const w = walletFromEnv();
|
|
79
|
+
> const pending = await getPendingApprovals(w);
|
|
80
|
+
> if (pending.length > 0) await approveTransaction(w, pending[0].txId);
|
|
81
|
+
> console.log('Approved');
|
|
82
|
+
> });
|
|
83
|
+
> "
|
|
84
|
+
> ```
|
|
85
|
+
|
|
86
|
+
### What just happened
|
|
87
|
+
|
|
88
|
+
1. `walletFromEnv()` read your private key from `AGENT_PRIVATE_KEY`, connected
|
|
89
|
+
to Base Sepolia via `RPC_URL`, and instantiated the `AgentAccountV2` smart
|
|
90
|
+
wallet at `AGENT_WALLET_ADDRESS`.
|
|
91
|
+
2. `setPolicyFromEnv()` wrote a spend policy on-chain: USDC transfers up to
|
|
92
|
+
`SPEND_LIMIT_PER_TX` per tx and `SPEND_LIMIT_DAILY` per day execute
|
|
93
|
+
autonomously. Anything above is queued.
|
|
94
|
+
3. `agentExecute()` called `agentExecute()` on the smart contract, which checked
|
|
95
|
+
the native ETH policy and sent 1 wei to the burn address.
|
|
96
|
+
4. The tx hash was returned immediately — you can verify it on
|
|
97
|
+
View on [Base Sepolia Explorer](https://sepolia.basescan.org/tx/{txHash}).
|
|
98
|
+
|
|
99
|
+
---
|
|
100
|
+
|
|
101
|
+
## Path B: Python (via agentpay-mcp over MCP)
|
|
102
|
+
|
|
103
|
+
**Under 15 lines.** Uses the official `mcp` Python SDK to connect to the
|
|
104
|
+
`agentpay-mcp` server and call `send_payment` over the Model Context Protocol.
|
|
105
|
+
|
|
106
|
+
```bash
|
|
107
|
+
pip install mcp python-dotenv
|
|
108
|
+
npx clawpowers mcp start # starts agentpay-mcp on stdio or a local port
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
```python
|
|
112
|
+
# first_tx.py
|
|
113
|
+
import asyncio
|
|
114
|
+
import os
|
|
115
|
+
from dotenv import load_dotenv
|
|
116
|
+
from mcp import ClientSession, StdioServerParameters
|
|
117
|
+
from mcp.client.stdio import stdio_client
|
|
118
|
+
|
|
119
|
+
load_dotenv()
|
|
120
|
+
|
|
121
|
+
async def main():
|
|
122
|
+
server = StdioServerParameters(
|
|
123
|
+
command="npx",
|
|
124
|
+
args=["agentpay-mcp"],
|
|
125
|
+
env={**os.environ}, # passes AGENT_PRIVATE_KEY, AGENT_WALLET_ADDRESS, etc.
|
|
126
|
+
)
|
|
127
|
+
async with stdio_client(server) as (read, write):
|
|
128
|
+
async with ClientSession(read, write) as session:
|
|
129
|
+
await session.initialize()
|
|
130
|
+
|
|
131
|
+
result = await session.call_tool("send_payment", {
|
|
132
|
+
"to": "0x000000000000000000000000000000000000dEaD",
|
|
133
|
+
"amount": "0.001", # USDC
|
|
134
|
+
"asset": "USDC",
|
|
135
|
+
"chain": "base-sepolia",
|
|
136
|
+
"reason": "first transaction test",
|
|
137
|
+
})
|
|
138
|
+
print(f"✅ txHash: {result.content[0].text}")
|
|
139
|
+
|
|
140
|
+
asyncio.run(main())
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
```bash
|
|
144
|
+
python first_tx.py
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
**Expected output:**
|
|
148
|
+
```
|
|
149
|
+
✅ txHash: 0x8b2d...f410
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
### What just happened
|
|
153
|
+
|
|
154
|
+
1. `stdio_client` spawned `agentpay-mcp` as a subprocess — the MCP server
|
|
155
|
+
loaded your `.env` credentials and connected to Base Sepolia.
|
|
156
|
+
2. `session.call_tool("send_payment", ...)` sent an MCP tool call over stdio,
|
|
157
|
+
which the server translated into an `agentTransferToken()` call on your
|
|
158
|
+
`AgentAccountV2` smart wallet.
|
|
159
|
+
3. The server returned the transaction hash, which you can verify at
|
|
160
|
+
View on [Base Sepolia Explorer](https://sepolia.basescan.org).
|
|
161
|
+
|
|
162
|
+
> **Python + MCP** is ideal when your agent framework is Python-based
|
|
163
|
+
> (LangChain, AutoGen, CrewAI) and you want to avoid writing viem/TypeScript.
|
|
164
|
+
> The MCP server handles all wallet logic; your Python code just calls tools.
|
|
165
|
+
|
|
166
|
+
---
|
|
167
|
+
|
|
168
|
+
## Verify Your Transaction
|
|
169
|
+
|
|
170
|
+
Both paths produce a `txHash`. Verify on-chain:
|
|
171
|
+
|
|
172
|
+
```bash
|
|
173
|
+
# Quick verification via cast (Foundry)
|
|
174
|
+
cast tx $TX_HASH --rpc-url https://sepolia.base.org
|
|
175
|
+
|
|
176
|
+
# Or open in browser
|
|
177
|
+
echo "https://sepolia.basescan.org/tx/$TX_HASH"
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
---
|
|
181
|
+
|
|
182
|
+
## Next Steps
|
|
183
|
+
|
|
184
|
+
| Goal | Resource |
|
|
185
|
+
|------|----------|
|
|
186
|
+
| Set up x402 automatic payments | `skills/agent-payments/SKILL.md` |
|
|
187
|
+
| Enable premium enrichment in prospecting | `skills/prospecting/SKILL.md` → "Premium Enrichment" section |
|
|
188
|
+
| Post a task bounty for another agent | `skills/agent-bounties/SKILL.md` |
|
|
189
|
+
| Review payment history | `npx clawpowers payments log` |
|
|
190
|
+
| Configure spending limits interactively | `npx clawpowers payments setup` (setup wizard) |
|
|
191
|
+
| Demo — see the full x402 flow in 60s | `runtime/demo/README.md` |
|
|
192
|
+
|
|
193
|
+
---
|
|
194
|
+
|
|
195
|
+
## Troubleshooting
|
|
196
|
+
|
|
197
|
+
| Error | Fix |
|
|
198
|
+
|-------|-----|
|
|
199
|
+
| `AGENT_PRIVATE_KEY environment variable is required` | Check your `.env` file exists and is loaded |
|
|
200
|
+
| `Unsupported chain: base-sepolia` | Ensure `agentwallet-sdk` is v0.3+ |
|
|
201
|
+
| `executed: false` (queued) | Amount > spend policy; lower `SPEND_LIMIT_PER_TX` or approve manually |
|
|
202
|
+
| `insufficient funds` | Get Base Sepolia ETH from the faucet link above |
|
|
203
|
+
| `nonce too low` | Another tx is pending; wait for confirmation or reset nonce |
|
|
204
|
+
| MCP: `spawn npx ENOENT` | Run `npm install -g agentpay-mcp` or use `npx --yes` |
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "clawpowers",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.4",
|
|
4
4
|
"description": "The skills framework that actually does something — runtime execution, persistent memory, self-improvement, and autonomous payments for coding agents.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "AI Agent Economy <https://github.com/up2itnow0822>",
|
|
@@ -30,7 +30,8 @@
|
|
|
30
30
|
},
|
|
31
31
|
"scripts": {
|
|
32
32
|
"init": "node bin/clawpowers.js init",
|
|
33
|
-
"test": "bash tests/run_all.sh"
|
|
33
|
+
"test": "bash tests/run_all.sh",
|
|
34
|
+
"lint": "eslint bin/ runtime/"
|
|
34
35
|
},
|
|
35
36
|
"files": [
|
|
36
37
|
"bin/",
|
|
@@ -51,5 +52,8 @@
|
|
|
51
52
|
"engines": {
|
|
52
53
|
"node": ">=16.0.0"
|
|
53
54
|
},
|
|
54
|
-
"
|
|
55
|
+
"devDependencies": {
|
|
56
|
+
"eslint": "10.1.0",
|
|
57
|
+
"globals": "17.4.0"
|
|
58
|
+
}
|
|
55
59
|
}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
# x402 Demo — Agent Payments in 60 Seconds
|
|
2
|
+
|
|
3
|
+
HTTP has a 402 status code that basically nobody used — until agents needed to pay.
|
|
4
|
+
|
|
5
|
+
This demo runs a local mock x402 merchant so you can see the full payment flow without any real money.
|
|
6
|
+
|
|
7
|
+
## Quick Start
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
# Terminal 1: Start the mock merchant
|
|
11
|
+
npx clawpowers demo x402
|
|
12
|
+
|
|
13
|
+
# Terminal 2: Hit the paid endpoint
|
|
14
|
+
curl http://localhost:PORT/api/premium-data
|
|
15
|
+
# → Returns 402 with payment requirements
|
|
16
|
+
|
|
17
|
+
# Simulate payment
|
|
18
|
+
curl -H "x-payment: mock-proof" http://localhost:PORT/api/premium-data
|
|
19
|
+
# → Returns 200 with data
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## What's Happening
|
|
23
|
+
|
|
24
|
+
1. Your agent calls a premium API
|
|
25
|
+
2. The server returns **HTTP 402 Payment Required** with x402 payment requirements (amount, asset, recipient, network)
|
|
26
|
+
3. ClawPowers evaluates the payment against your spending policy (limits, allowlist, mode)
|
|
27
|
+
4. In **dry-run mode**: logs what would happen, no funds move
|
|
28
|
+
5. In **live mode**: signs a payment proof via `agentwallet-sdk`, sends payment, retries the request
|
|
29
|
+
6. Server validates payment proof and returns the data
|
|
30
|
+
|
|
31
|
+
## The x402 Flow
|
|
32
|
+
|
|
33
|
+
```
|
|
34
|
+
Agent Mock Merchant
|
|
35
|
+
| |
|
|
36
|
+
|-- GET /api/premium-data ->|
|
|
37
|
+
|<- 402 + requirements -----|
|
|
38
|
+
| |
|
|
39
|
+
| [evaluate policy] |
|
|
40
|
+
| [sign payment proof] |
|
|
41
|
+
| |
|
|
42
|
+
|-- GET + x-payment ------->|
|
|
43
|
+
|<- 200 + data -------------|
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## Payment Requirements Format
|
|
47
|
+
|
|
48
|
+
The 402 response includes a JSON body:
|
|
49
|
+
|
|
50
|
+
```json
|
|
51
|
+
{
|
|
52
|
+
"x402Version": 1,
|
|
53
|
+
"accepts": [{
|
|
54
|
+
"scheme": "exact",
|
|
55
|
+
"network": "base-sepolia",
|
|
56
|
+
"maxAmountRequired": "100000",
|
|
57
|
+
"resource": "https://localhost:PORT/api/premium-data",
|
|
58
|
+
"asset": "0x036CbD53842c5426634e7929541eC2318f3dCF7e",
|
|
59
|
+
"payTo": "0xff86829393C6C26A4EC122bE0Cc3E466Ef876AdD"
|
|
60
|
+
}],
|
|
61
|
+
"error": "Payment Required"
|
|
62
|
+
}
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
## Check Payment Logs
|
|
66
|
+
|
|
67
|
+
After running the demo, inspect the payment decisions:
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
npx clawpowers payments log
|
|
71
|
+
npx clawpowers payments summary
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
## Next Steps
|
|
75
|
+
|
|
76
|
+
- Read the [agent-payments skill](../../skills/agent-payments/SKILL.md) for full methodology
|
|
77
|
+
- Run `npx clawpowers payments setup` to configure spending limits
|
|
78
|
+
- See the [Security Model](../../README.md#security-model) for guardrails
|
package/runtime/init.sh
CHANGED
|
@@ -132,7 +132,7 @@ EOF
|
|
|
132
132
|
# The sed command replaces the version= line in place; .bak is cleaned up immediately.
|
|
133
133
|
run_migrations() {
|
|
134
134
|
local current_version
|
|
135
|
-
current_version=$(grep "^version=" "$CLAWPOWERS_DIR/.version" 2>/dev/null | cut -d= -f2 || echo "0.0.0")
|
|
135
|
+
# current_version=$(grep "^version=" "$CLAWPOWERS_DIR/.version" 2>/dev/null | cut -d= -f2 || echo "0.0.0")
|
|
136
136
|
|
|
137
137
|
# Future migration hooks go here, e.g.:
|
|
138
138
|
# if [[ "$current_version" < "2.0.0" ]]; then
|