@clawpay-hedera/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/README.md +294 -0
- package/dist/cli/index.d.ts +3 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +137 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/client/hedera-payment.d.ts +25 -0
- package/dist/client/hedera-payment.d.ts.map +1 -0
- package/dist/client/hedera-payment.js +68 -0
- package/dist/client/hedera-payment.js.map +1 -0
- package/dist/client/with-x402-client.d.ts +27 -0
- package/dist/client/with-x402-client.d.ts.map +1 -0
- package/dist/client/with-x402-client.js +136 -0
- package/dist/client/with-x402-client.js.map +1 -0
- package/dist/client.d.ts +2 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +2 -0
- package/dist/client.js.map +1 -0
- package/dist/handler/proxy/hooks/analytics-hook.d.ts +299 -0
- package/dist/handler/proxy/hooks/analytics-hook.d.ts.map +1 -0
- package/dist/handler/proxy/hooks/analytics-hook.js +133 -0
- package/dist/handler/proxy/hooks/analytics-hook.js.map +1 -0
- package/dist/handler/proxy/hooks/auth-headers-hook.d.ts +20 -0
- package/dist/handler/proxy/hooks/auth-headers-hook.d.ts.map +1 -0
- package/dist/handler/proxy/hooks/auth-headers-hook.js +34 -0
- package/dist/handler/proxy/hooks/auth-headers-hook.js.map +1 -0
- package/dist/handler/proxy/hooks/hcs-audit-hook.d.ts +133 -0
- package/dist/handler/proxy/hooks/hcs-audit-hook.d.ts.map +1 -0
- package/dist/handler/proxy/hooks/hcs-audit-hook.js +138 -0
- package/dist/handler/proxy/hooks/hcs-audit-hook.js.map +1 -0
- package/dist/handler/proxy/hooks/logging-hook.d.ts +100 -0
- package/dist/handler/proxy/hooks/logging-hook.d.ts.map +1 -0
- package/dist/handler/proxy/hooks/logging-hook.js +14 -0
- package/dist/handler/proxy/hooks/logging-hook.js.map +1 -0
- package/dist/handler/proxy/hooks/x402-hook.d.ts +246 -0
- package/dist/handler/proxy/hooks/x402-hook.d.ts.map +1 -0
- package/dist/handler/proxy/hooks/x402-hook.js +219 -0
- package/dist/handler/proxy/hooks/x402-hook.js.map +1 -0
- package/dist/handler/proxy/hooks.d.ts +12111 -0
- package/dist/handler/proxy/hooks.d.ts.map +1 -0
- package/dist/handler/proxy/hooks.js +142 -0
- package/dist/handler/proxy/hooks.js.map +1 -0
- package/dist/handler/proxy/index.d.ts +3 -0
- package/dist/handler/proxy/index.d.ts.map +1 -0
- package/dist/handler/proxy/index.js +489 -0
- package/dist/handler/proxy/index.js.map +1 -0
- package/dist/handler/server/index.d.ts +25 -0
- package/dist/handler/server/index.d.ts.map +1 -0
- package/dist/handler/server/index.js +38 -0
- package/dist/handler/server/index.js.map +1 -0
- package/dist/handler/server/platform-detection.d.ts +32 -0
- package/dist/handler/server/platform-detection.d.ts.map +1 -0
- package/dist/handler/server/platform-detection.js +441 -0
- package/dist/handler/server/platform-detection.js.map +1 -0
- package/dist/handler/server/plugins/with-x402.d.ts +21 -0
- package/dist/handler/server/plugins/with-x402.d.ts.map +1 -0
- package/dist/handler/server/plugins/with-x402.js +290 -0
- package/dist/handler/server/plugins/with-x402.js.map +1 -0
- package/dist/handler/server/templates/x402-server.d.ts +16 -0
- package/dist/handler/server/templates/x402-server.d.ts.map +1 -0
- package/dist/handler/server/templates/x402-server.js +13 -0
- package/dist/handler/server/templates/x402-server.js.map +1 -0
- package/dist/handler/shared/hedera-price.d.ts +26 -0
- package/dist/handler/shared/hedera-price.d.ts.map +1 -0
- package/dist/handler/shared/hedera-price.js +54 -0
- package/dist/handler/shared/hedera-price.js.map +1 -0
- package/dist/handler.d.ts +14 -0
- package/dist/handler.d.ts.map +1 -0
- package/dist/handler.js +12 -0
- package/dist/handler.js.map +1 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +5 -0
- package/dist/index.js.map +1 -0
- package/dist/networks/hedera.d.ts +52 -0
- package/dist/networks/hedera.d.ts.map +1 -0
- package/dist/networks/hedera.js +61 -0
- package/dist/networks/hedera.js.map +1 -0
- package/dist/server/stdio/index.d.ts +2 -0
- package/dist/server/stdio/index.d.ts.map +1 -0
- package/dist/server/stdio/index.js +91 -0
- package/dist/server/stdio/index.js.map +1 -0
- package/dist/server/stdio/proxy-server.d.ts +9 -0
- package/dist/server/stdio/proxy-server.d.ts.map +1 -0
- package/dist/server/stdio/proxy-server.js +53 -0
- package/dist/server/stdio/proxy-server.js.map +1 -0
- package/dist/server/stdio/start-stdio-server.d.ts +28 -0
- package/dist/server/stdio/start-stdio-server.d.ts.map +1 -0
- package/dist/server/stdio/start-stdio-server.js +84 -0
- package/dist/server/stdio/start-stdio-server.js.map +1 -0
- package/dist/server.d.ts +6 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +4 -0
- package/dist/server.js.map +1 -0
- package/dist/utils/signer.d.ts +4 -0
- package/dist/utils/signer.d.ts.map +1 -0
- package/dist/utils/signer.js +58 -0
- package/dist/utils/signer.js.map +1 -0
- package/dist/utils.d.ts +2 -0
- package/dist/utils.d.ts.map +1 -0
- package/dist/utils.js +2 -0
- package/dist/utils.js.map +1 -0
- package/package.json +86 -0
package/README.md
ADDED
|
@@ -0,0 +1,294 @@
|
|
|
1
|
+
# @clawpay-hedera/sdk
|
|
2
|
+
|
|
3
|
+
SDK and CLI for ClawPay — autonomous MCP micropayments for AI agents on Hedera. Enables any MCP-compatible AI agent (Claude, Cursor, ChatGPT, OpenClaw, etc.) to autonomously pay for tool calls using the x402 HTTP payment protocol with USDC on Hedera.
|
|
4
|
+
|
|
5
|
+
- 🔌 Connect to multiple MCP servers at once (stdio proxy)
|
|
6
|
+
- 💳 Handle 402 Payment Required automatically (x402 on Hedera)
|
|
7
|
+
- 📦 Programmatic APIs for both clients and servers
|
|
8
|
+
- 🦞 Hedera-native: HTS USDC payments, HCS audit trails, Blocky402 settlement
|
|
9
|
+
|
|
10
|
+
## Quick Start
|
|
11
|
+
|
|
12
|
+
Connect to a paid MCP server with automatic Hedera x402 payments:
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
npx @clawpay-hedera/sdk connect \
|
|
16
|
+
--urls "https://your-server.com/mcp" \
|
|
17
|
+
--hedera-key 0xYOUR_ECDSA_PRIVATE_KEY \
|
|
18
|
+
--hedera-account 0.0.YOUR_ACCOUNT_ID
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
This starts an MCP stdio proxy that intercepts 402 responses, creates partially-signed HTS USDC transfers, and retries with payment — all automatically.
|
|
22
|
+
|
|
23
|
+
## Installation
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
npm i @clawpay-hedera/sdk
|
|
27
|
+
# or
|
|
28
|
+
pnpm i @clawpay-hedera/sdk
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## CLI
|
|
32
|
+
|
|
33
|
+
### Commands
|
|
34
|
+
|
|
35
|
+
- `clawpay connect` — start an MCP stdio proxy with Hedera x402 payments
|
|
36
|
+
- `clawpay version` — show version information
|
|
37
|
+
|
|
38
|
+
### Options
|
|
39
|
+
|
|
40
|
+
| Option | Description | Default |
|
|
41
|
+
|--------|-------------|---------|
|
|
42
|
+
| `-u, --urls <urls>` | Comma-separated list of MCP server URLs | Required |
|
|
43
|
+
| `-a, --api-key <key>` | API key for ClawPay proxy authentication | `API_KEY` env |
|
|
44
|
+
| `--hedera-key <privateKey>` | Hedera ECDSA private key (0x-prefixed) | `HEDERA_PRIVATE_KEY` env |
|
|
45
|
+
| `--hedera-account <accountId>` | Hedera account ID (e.g. 0.0.6514537) | `HEDERA_ACCOUNT_ID` env |
|
|
46
|
+
| `--hedera-network <network>` | `hedera-testnet` or `hedera` (mainnet) | `hedera-testnet` |
|
|
47
|
+
| `--max-atomic <value>` | Max payment in atomic units (e.g. 100000 = 0.1 USDC) | `X402_MAX_ATOMIC` env |
|
|
48
|
+
|
|
49
|
+
### Examples
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
# Direct Hedera key (recommended for agents)
|
|
53
|
+
npx @clawpay-hedera/sdk connect \
|
|
54
|
+
--urls "https://your-server.com/mcp" \
|
|
55
|
+
--hedera-key 0xYOUR_ECDSA_KEY \
|
|
56
|
+
--hedera-account 0.0.1234567
|
|
57
|
+
|
|
58
|
+
# Multiple servers
|
|
59
|
+
npx @clawpay-hedera/sdk connect \
|
|
60
|
+
--urls "https://server1.com/mcp,https://server2.com/mcp" \
|
|
61
|
+
--hedera-key $HEDERA_PRIVATE_KEY \
|
|
62
|
+
--hedera-account $HEDERA_ACCOUNT_ID
|
|
63
|
+
|
|
64
|
+
# Using API key (via ClawPay proxy)
|
|
65
|
+
npx @clawpay-hedera/sdk connect \
|
|
66
|
+
--urls "https://clawpay-proxy.com/mcp" \
|
|
67
|
+
--api-key clawpay_YOUR_API_KEY
|
|
68
|
+
|
|
69
|
+
# Custom max payment (500000 = 0.5 USDC)
|
|
70
|
+
npx @clawpay-hedera/sdk connect \
|
|
71
|
+
--urls "https://your-server.com/mcp" \
|
|
72
|
+
--hedera-key $HEDERA_PRIVATE_KEY \
|
|
73
|
+
--hedera-account $HEDERA_ACCOUNT_ID \
|
|
74
|
+
--max-atomic 500000
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
### Behavior
|
|
78
|
+
|
|
79
|
+
- With `--hedera-key`: the proxy uses x402 Payment transport — creates partially-signed HTS USDC transfers and settles via Blocky402 facilitator on Hedera.
|
|
80
|
+
- With `--api-key`: the proxy forwards the key to the ClawPay proxy service, which signs payments on your behalf using your stored encrypted Hedera key.
|
|
81
|
+
- Default max payment: 0.1 USDC (100000 atomic units). Override with `--max-atomic`.
|
|
82
|
+
|
|
83
|
+
## MCP Client Configuration
|
|
84
|
+
|
|
85
|
+
### Claude Desktop / Cursor / Windsurf
|
|
86
|
+
|
|
87
|
+
Add to your MCP client config (e.g. `claude_desktop_config.json`):
|
|
88
|
+
|
|
89
|
+
```json
|
|
90
|
+
{
|
|
91
|
+
"mcpServers": {
|
|
92
|
+
"hedera-tools": {
|
|
93
|
+
"command": "npx",
|
|
94
|
+
"args": [
|
|
95
|
+
"@clawpay-hedera/sdk",
|
|
96
|
+
"connect",
|
|
97
|
+
"--urls",
|
|
98
|
+
"https://your-server.com/mcp",
|
|
99
|
+
"--hedera-key",
|
|
100
|
+
"0xYOUR_ECDSA_PRIVATE_KEY",
|
|
101
|
+
"--hedera-account",
|
|
102
|
+
"0.0.YOUR_ACCOUNT_ID"
|
|
103
|
+
]
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
### Using API Key (Alternative)
|
|
110
|
+
|
|
111
|
+
If you've linked your wallet on the ClawPay dashboard and created an API key:
|
|
112
|
+
|
|
113
|
+
```json
|
|
114
|
+
{
|
|
115
|
+
"mcpServers": {
|
|
116
|
+
"hedera-tools": {
|
|
117
|
+
"command": "npx",
|
|
118
|
+
"args": [
|
|
119
|
+
"@clawpay-hedera/sdk",
|
|
120
|
+
"connect",
|
|
121
|
+
"--urls",
|
|
122
|
+
"https://your-server.com/mcp",
|
|
123
|
+
"--api-key",
|
|
124
|
+
"clawpay_YOUR_API_KEY"
|
|
125
|
+
]
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
## SDK Usage
|
|
132
|
+
|
|
133
|
+
### Client: x402 Payment Wrapper
|
|
134
|
+
|
|
135
|
+
Wrap any MCP client with automatic Hedera x402 payment handling:
|
|
136
|
+
|
|
137
|
+
```ts
|
|
138
|
+
import { Client } from '@modelcontextprotocol/sdk/client/index.js'
|
|
139
|
+
import { StreamableHTTPClientTransport } from '@modelcontextprotocol/sdk/client/streamableHttp.js'
|
|
140
|
+
import { withX402Client } from '@clawpay-hedera/sdk/client'
|
|
141
|
+
|
|
142
|
+
const client = new Client(
|
|
143
|
+
{ name: 'my-agent', version: '1.0.0' },
|
|
144
|
+
{ capabilities: {} }
|
|
145
|
+
)
|
|
146
|
+
|
|
147
|
+
const transport = new StreamableHTTPClientTransport(
|
|
148
|
+
new URL('https://your-server.com/mcp')
|
|
149
|
+
)
|
|
150
|
+
await client.connect(transport)
|
|
151
|
+
|
|
152
|
+
// Wrap with Hedera x402 payment capabilities
|
|
153
|
+
const paymentClient = withX402Client(client, {
|
|
154
|
+
hederaConfig: {
|
|
155
|
+
privateKey: '0xYOUR_ECDSA_KEY',
|
|
156
|
+
network: 'testnet',
|
|
157
|
+
payerAccountId: '0.0.YOUR_ACCOUNT_ID',
|
|
158
|
+
facilitatorFeePayer: '0.0.7162784', // Blocky402
|
|
159
|
+
},
|
|
160
|
+
maxPaymentValue: BigInt(0.1 * 10 ** 6), // 0.1 USDC max
|
|
161
|
+
confirmationCallback: async () => true, // Auto-approve payments
|
|
162
|
+
})
|
|
163
|
+
|
|
164
|
+
// Use tools — payments happen automatically on 402
|
|
165
|
+
const tools = await paymentClient.listTools()
|
|
166
|
+
const result = await paymentClient.callTool({
|
|
167
|
+
name: 'hbar_account_balance',
|
|
168
|
+
arguments: { accountId: '0.0.1234567' }
|
|
169
|
+
})
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
### Server: Protecting Tools with Payments
|
|
173
|
+
|
|
174
|
+
Use `createMcpPaidHandler` to add x402 paywalls to your MCP tools:
|
|
175
|
+
|
|
176
|
+
```ts
|
|
177
|
+
import { createMcpPaidHandler } from '@clawpay-hedera/sdk/handler'
|
|
178
|
+
import { z } from 'zod'
|
|
179
|
+
|
|
180
|
+
const handler = createMcpPaidHandler(
|
|
181
|
+
(server) => {
|
|
182
|
+
server.paidTool(
|
|
183
|
+
'my_tool',
|
|
184
|
+
'Description of what this tool does',
|
|
185
|
+
'$0.05', // Price in USD (charged in USDC on Hedera)
|
|
186
|
+
{ input: z.string().describe('Input parameter') },
|
|
187
|
+
{ readOnlyHint: true },
|
|
188
|
+
async ({ input }) => ({
|
|
189
|
+
content: [{ type: 'text', text: `Result: ${input}` }]
|
|
190
|
+
})
|
|
191
|
+
)
|
|
192
|
+
},
|
|
193
|
+
{
|
|
194
|
+
name: 'My Paid Server',
|
|
195
|
+
version: '1.0.0',
|
|
196
|
+
},
|
|
197
|
+
{
|
|
198
|
+
recipient: '0xYOUR_EVM_ADDRESS', // Where you receive USDC payments
|
|
199
|
+
facilitator: {
|
|
200
|
+
url: 'https://api.testnet.blocky402.com',
|
|
201
|
+
},
|
|
202
|
+
}
|
|
203
|
+
)
|
|
204
|
+
|
|
205
|
+
// Use with Hono, Express, or any framework
|
|
206
|
+
import { Hono } from 'hono'
|
|
207
|
+
const app = new Hono()
|
|
208
|
+
app.all('/mcp', (c) => handler(c.req.raw))
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
### Programmatic Stdio Proxy
|
|
212
|
+
|
|
213
|
+
```ts
|
|
214
|
+
import { startStdioServer, ServerType } from '@clawpay-hedera/sdk'
|
|
215
|
+
|
|
216
|
+
const serverConnections = [{
|
|
217
|
+
url: 'https://your-server.com/mcp',
|
|
218
|
+
serverType: ServerType.HTTPStream,
|
|
219
|
+
}]
|
|
220
|
+
|
|
221
|
+
await startStdioServer({
|
|
222
|
+
serverConnections,
|
|
223
|
+
x402ClientConfig: {
|
|
224
|
+
hederaConfig: {
|
|
225
|
+
privateKey: '0xYOUR_ECDSA_KEY',
|
|
226
|
+
network: 'testnet',
|
|
227
|
+
payerAccountId: '0.0.YOUR_ACCOUNT_ID',
|
|
228
|
+
facilitatorFeePayer: '0.0.7162784',
|
|
229
|
+
},
|
|
230
|
+
maxPaymentValue: BigInt(0.1 * 10 ** 6),
|
|
231
|
+
confirmationCallback: async () => true,
|
|
232
|
+
},
|
|
233
|
+
})
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
## How Payment Works
|
|
237
|
+
|
|
238
|
+
When an agent calls a paid tool:
|
|
239
|
+
|
|
240
|
+
1. Agent sends `tools/call` request to the MCP server
|
|
241
|
+
2. Server returns a 402 response with payment requirements (network, asset, amount, recipient)
|
|
242
|
+
3. The SDK creates a partially-signed HTS USDC transfer on Hedera with Blocky402 as fee payer
|
|
243
|
+
4. SDK retries the request with the `X-PAYMENT` header containing the signed transaction
|
|
244
|
+
5. Server forwards payment to Blocky402 facilitator for verification
|
|
245
|
+
6. Blocky402 co-signs, submits to Hedera, and settles the USDC transfer
|
|
246
|
+
7. Agent receives the tool result
|
|
247
|
+
|
|
248
|
+
The entire flow is autonomous — no human intervention needed.
|
|
249
|
+
|
|
250
|
+
## Environment Variables
|
|
251
|
+
|
|
252
|
+
| Variable | Description |
|
|
253
|
+
|----------|-------------|
|
|
254
|
+
| `HEDERA_PRIVATE_KEY` | Hedera ECDSA private key (0x-prefixed) |
|
|
255
|
+
| `HEDERA_ACCOUNT_ID` | Hedera account ID (e.g. 0.0.6514537) |
|
|
256
|
+
| `HEDERA_NETWORK` | `hedera-testnet` (default) or `hedera` |
|
|
257
|
+
| `API_KEY` | ClawPay API key for proxy authentication |
|
|
258
|
+
| `X402_MAX_ATOMIC` | Max payment in atomic units |
|
|
259
|
+
|
|
260
|
+
## Supported Network
|
|
261
|
+
|
|
262
|
+
- **Hedera Testnet** (`hedera-testnet`) — USDC token `0.0.5449`
|
|
263
|
+
- **Hedera Mainnet** (`hedera`) — USDC token `0.0.456858`
|
|
264
|
+
|
|
265
|
+
Settlement via [Blocky402](https://blocky402.com) facilitator (account `0.0.7162784` on testnet).
|
|
266
|
+
|
|
267
|
+
## Dependencies
|
|
268
|
+
|
|
269
|
+
- `@modelcontextprotocol/sdk` — MCP protocol implementation
|
|
270
|
+
- `@hashgraph/sdk` — Hedera SDK for HTS transfers
|
|
271
|
+
- `x402` — x402 payment protocol types
|
|
272
|
+
- `viem` — EVM utilities (used for Hedera EVM relay compatibility)
|
|
273
|
+
- `commander` — CLI framework
|
|
274
|
+
- `zod` — Schema validation
|
|
275
|
+
- `mcp-handler` — MCP server handler utilities
|
|
276
|
+
|
|
277
|
+
## Security
|
|
278
|
+
|
|
279
|
+
- Never commit private keys. Use environment variables.
|
|
280
|
+
- Use `maxPaymentValue` to cap per-transaction spend.
|
|
281
|
+
- The Blocky402 facilitator only co-signs valid, pre-authorized transfers.
|
|
282
|
+
- For production, consider using the ClawPay proxy with encrypted key storage instead of passing keys directly.
|
|
283
|
+
|
|
284
|
+
## Development
|
|
285
|
+
|
|
286
|
+
```bash
|
|
287
|
+
pnpm i
|
|
288
|
+
pnpm run build
|
|
289
|
+
pnpm run dev # watch mode
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
## License
|
|
293
|
+
|
|
294
|
+
MIT
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { Command } from "commander";
|
|
3
|
+
import { config } from "dotenv";
|
|
4
|
+
import { createWalletClient, http, defineChain } from "viem";
|
|
5
|
+
import { privateKeyToAccount } from "viem/accounts";
|
|
6
|
+
import { publicActions } from "viem";
|
|
7
|
+
import packageJson from '../../package.json' with { type: 'json' };
|
|
8
|
+
import { ServerType, startStdioServer } from '../server/stdio/start-stdio-server.js';
|
|
9
|
+
config();
|
|
10
|
+
const SUPPORTED_HEDERA_NETWORKS = ['hedera-testnet', 'hedera'];
|
|
11
|
+
// Custom Hedera chain definitions for viem
|
|
12
|
+
const hederaTestnet = defineChain({
|
|
13
|
+
id: 296,
|
|
14
|
+
name: 'Hedera Testnet',
|
|
15
|
+
nativeCurrency: { name: 'HBAR', symbol: 'HBAR', decimals: 18 },
|
|
16
|
+
rpcUrls: { default: { http: ['https://testnet.hashio.io/api'] } },
|
|
17
|
+
blockExplorers: { default: { name: 'HashScan', url: 'https://hashscan.io/testnet' } },
|
|
18
|
+
testnet: true,
|
|
19
|
+
});
|
|
20
|
+
const hederaMainnet = defineChain({
|
|
21
|
+
id: 295,
|
|
22
|
+
name: 'Hedera Mainnet',
|
|
23
|
+
nativeCurrency: { name: 'HBAR', symbol: 'HBAR', decimals: 18 },
|
|
24
|
+
rpcUrls: { default: { http: ['https://mainnet.hashio.io/api'] } },
|
|
25
|
+
blockExplorers: { default: { name: 'HashScan', url: 'https://hashscan.io/mainnet' } },
|
|
26
|
+
testnet: false,
|
|
27
|
+
});
|
|
28
|
+
function createHederaSigner(network, privateKey) {
|
|
29
|
+
const chain = network === 'hedera-testnet' ? hederaTestnet : hederaMainnet;
|
|
30
|
+
const account = privateKeyToAccount(privateKey);
|
|
31
|
+
return createWalletClient({ chain, transport: http(), account }).extend(publicActions);
|
|
32
|
+
}
|
|
33
|
+
const program = new Command();
|
|
34
|
+
program
|
|
35
|
+
.name('clawpay')
|
|
36
|
+
.description('ClawPay CLI — autonomous MCP micropayments for AI agents on Hedera')
|
|
37
|
+
.version(packageJson.version);
|
|
38
|
+
program
|
|
39
|
+
.command('connect')
|
|
40
|
+
.description('Start an MCP stdio proxy to remote servers with Hedera x402 payments')
|
|
41
|
+
.requiredOption('-u, --urls <urls>', 'Comma-separated list of MCP server URLs')
|
|
42
|
+
.option('-a, --api-key <key>', 'API key for authentication (env: API_KEY)')
|
|
43
|
+
.option('--max-atomic <value>', 'Max payment in atomic units (e.g. 100000 for 0.1 USDC). Env: X402_MAX_ATOMIC')
|
|
44
|
+
.option('--hedera-key <privateKey>', 'Hedera ECDSA private key (0x...) (env: HEDERA_PRIVATE_KEY)')
|
|
45
|
+
.option('--hedera-account <accountId>', 'Hedera account ID (e.g. 0.0.6514537) (env: HEDERA_ACCOUNT_ID)')
|
|
46
|
+
.option('--hedera-network <network>', 'Hedera network: hedera-testnet (default) or hedera (env: HEDERA_NETWORK)')
|
|
47
|
+
.action(async (options) => {
|
|
48
|
+
try {
|
|
49
|
+
const apiKey = options.apiKey || process.env.API_KEY;
|
|
50
|
+
const maxAtomicArg = options.maxAtomic || process.env.X402_MAX_ATOMIC;
|
|
51
|
+
const hederaKeyArg = options.hederaKey || process.env.HEDERA_PRIVATE_KEY;
|
|
52
|
+
const hederaAccountArg = options.hederaAccount || process.env.HEDERA_ACCOUNT_ID;
|
|
53
|
+
const hederaNetwork = (options.hederaNetwork || process.env.HEDERA_NETWORK || 'hedera-testnet');
|
|
54
|
+
if (!apiKey && !hederaKeyArg) {
|
|
55
|
+
console.error('Error: Provide either --api-key or --hedera-key (env: HEDERA_PRIVATE_KEY).');
|
|
56
|
+
process.exit(1);
|
|
57
|
+
}
|
|
58
|
+
if (hederaKeyArg && !SUPPORTED_HEDERA_NETWORKS.includes(hederaNetwork)) {
|
|
59
|
+
console.error(`Error: Invalid network '${hederaNetwork}'. Supported: ${SUPPORTED_HEDERA_NETWORKS.join(', ')}`);
|
|
60
|
+
process.exit(1);
|
|
61
|
+
}
|
|
62
|
+
const serverType = ServerType.HTTPStream;
|
|
63
|
+
const serverUrls = options.urls.split(',').map((url) => url.trim());
|
|
64
|
+
if (serverUrls.length === 0) {
|
|
65
|
+
console.error('Error: At least one server URL is required.');
|
|
66
|
+
process.exit(1);
|
|
67
|
+
}
|
|
68
|
+
// Determine proxy mode (API key with proxy URLs)
|
|
69
|
+
const isProxyMode = apiKey && serverUrls.some(url => url.includes('/v1/mcp') || url.includes('clawpay') || url.includes('clawpay-hedera') || url.includes('proxy'));
|
|
70
|
+
if (apiKey && !isProxyMode) {
|
|
71
|
+
console.error('Error: API key can only be used with proxy URLs. Use --hedera-key for direct x402 payments.');
|
|
72
|
+
process.exit(1);
|
|
73
|
+
}
|
|
74
|
+
const serverConnections = serverUrls.map(url => {
|
|
75
|
+
const isProxyUrl = url.includes('/v1/mcp') || url.includes('clawpay') || url.includes('clawpay-hedera') || url.includes('proxy');
|
|
76
|
+
let transportOptions = undefined;
|
|
77
|
+
if (apiKey && isProxyUrl) {
|
|
78
|
+
transportOptions = {
|
|
79
|
+
requestInit: {
|
|
80
|
+
credentials: 'include',
|
|
81
|
+
headers: new Headers({ 'x-api-key': apiKey })
|
|
82
|
+
}
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
return { url, serverType, transportOptions };
|
|
86
|
+
});
|
|
87
|
+
// X402 client config (when using Hedera key directly)
|
|
88
|
+
let x402ClientConfig = undefined;
|
|
89
|
+
if (!apiKey && hederaKeyArg) {
|
|
90
|
+
const pk = hederaKeyArg.trim();
|
|
91
|
+
if (!pk.startsWith('0x') || pk.length !== 66) {
|
|
92
|
+
console.error('Error: Invalid --hedera-key. Must be 0x-prefixed 64-hex ECDSA key.');
|
|
93
|
+
process.exit(1);
|
|
94
|
+
}
|
|
95
|
+
try {
|
|
96
|
+
const signer = createHederaSigner(hederaNetwork, pk);
|
|
97
|
+
const maybeMax = maxAtomicArg ? (() => { try {
|
|
98
|
+
return BigInt(maxAtomicArg);
|
|
99
|
+
}
|
|
100
|
+
catch {
|
|
101
|
+
return undefined;
|
|
102
|
+
} })() : undefined;
|
|
103
|
+
x402ClientConfig = {
|
|
104
|
+
wallet: { evm: signer },
|
|
105
|
+
hederaConfig: {
|
|
106
|
+
privateKey: pk,
|
|
107
|
+
network: hederaNetwork === 'hedera' ? 'mainnet' : 'testnet',
|
|
108
|
+
payerAccountId: hederaAccountArg,
|
|
109
|
+
facilitatorFeePayer: '0.0.7162784', // Blocky402 fee payer
|
|
110
|
+
},
|
|
111
|
+
...(maybeMax !== undefined ? { maxPaymentValue: maybeMax } : {}),
|
|
112
|
+
confirmationCallback: async () => true,
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
catch (error) {
|
|
116
|
+
console.error(`Error: Failed to create Hedera signer:`, error instanceof Error ? error.message : String(error));
|
|
117
|
+
process.exit(1);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
await startStdioServer({ serverConnections, x402ClientConfig });
|
|
121
|
+
}
|
|
122
|
+
catch (error) {
|
|
123
|
+
console.error('Failed to start server:', error);
|
|
124
|
+
process.exit(1);
|
|
125
|
+
}
|
|
126
|
+
});
|
|
127
|
+
program
|
|
128
|
+
.command('version')
|
|
129
|
+
.description('Show version information')
|
|
130
|
+
.action(() => {
|
|
131
|
+
console.log('clawpay version ' + packageJson.version);
|
|
132
|
+
});
|
|
133
|
+
program.parse();
|
|
134
|
+
if (!process.argv.slice(2).length) {
|
|
135
|
+
program.outputHelp();
|
|
136
|
+
}
|
|
137
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Hedera-specific x402 payment header creation.
|
|
3
|
+
*
|
|
4
|
+
* Hedera x402 uses partially-signed HTS TokenTransfer transactions.
|
|
5
|
+
* The facilitator (Blocky402) is set as fee payer via TransactionId,
|
|
6
|
+
* then the payer partially signs. Blocky402 co-signs and submits.
|
|
7
|
+
*
|
|
8
|
+
* Key: outer payload must be { x402Version, payload: { transaction } }
|
|
9
|
+
* WITHOUT scheme/network in the outer object.
|
|
10
|
+
*/
|
|
11
|
+
import type { PaymentRequirements } from "x402/types";
|
|
12
|
+
export interface HederaPaymentConfig {
|
|
13
|
+
privateKey: string;
|
|
14
|
+
network: 'testnet' | 'mainnet';
|
|
15
|
+
payerAccountId?: string;
|
|
16
|
+
facilitatorFeePayer?: string;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Create a Hedera x402 payment header (partially-signed HTS transfer).
|
|
20
|
+
*
|
|
21
|
+
* TransactionId is generated with the facilitator's account so Blocky402
|
|
22
|
+
* pays the HBAR gas fee. The payer only partially signs the token transfer.
|
|
23
|
+
*/
|
|
24
|
+
export declare function createHederaPaymentHeader(config: HederaPaymentConfig, paymentRequirements: PaymentRequirements): Promise<string>;
|
|
25
|
+
//# sourceMappingURL=hedera-payment.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hedera-payment.d.ts","sourceRoot":"","sources":["../../src/client/hedera-payment.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAWH,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAQtD,MAAM,WAAW,mBAAmB;IAClC,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,SAAS,GAAG,SAAS,CAAC;IAC/B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,mBAAmB,CAAC,EAAE,MAAM,CAAC;CAC9B;AAED;;;;;GAKG;AACH,wBAAsB,yBAAyB,CAC7C,MAAM,EAAE,mBAAmB,EAC3B,mBAAmB,EAAE,mBAAmB,GACvC,OAAO,CAAC,MAAM,CAAC,CAqDjB"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Hedera-specific x402 payment header creation.
|
|
3
|
+
*
|
|
4
|
+
* Hedera x402 uses partially-signed HTS TokenTransfer transactions.
|
|
5
|
+
* The facilitator (Blocky402) is set as fee payer via TransactionId,
|
|
6
|
+
* then the payer partially signs. Blocky402 co-signs and submits.
|
|
7
|
+
*
|
|
8
|
+
* Key: outer payload must be { x402Version, payload: { transaction } }
|
|
9
|
+
* WITHOUT scheme/network in the outer object.
|
|
10
|
+
*/
|
|
11
|
+
import { Client, TransferTransaction, AccountId, TokenId, PrivateKey, TransactionId, Timestamp, } from "@hashgraph/sdk";
|
|
12
|
+
/** Convert EVM payTo address to Hedera AccountId */
|
|
13
|
+
function resolvePayTo(payTo) {
|
|
14
|
+
if (payTo.startsWith("0.0."))
|
|
15
|
+
return AccountId.fromString(payTo);
|
|
16
|
+
return AccountId.fromEvmAddress(0, 0, payTo);
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Create a Hedera x402 payment header (partially-signed HTS transfer).
|
|
20
|
+
*
|
|
21
|
+
* TransactionId is generated with the facilitator's account so Blocky402
|
|
22
|
+
* pays the HBAR gas fee. The payer only partially signs the token transfer.
|
|
23
|
+
*/
|
|
24
|
+
export async function createHederaPaymentHeader(config, paymentRequirements) {
|
|
25
|
+
const { privateKey: pkHex, network, payerAccountId: payerStr, facilitatorFeePayer } = config;
|
|
26
|
+
const pk = PrivateKey.fromStringECDSA(pkHex.replace(/^0x/, ''));
|
|
27
|
+
// Resolve payer account ID
|
|
28
|
+
let payerId;
|
|
29
|
+
if (payerStr) {
|
|
30
|
+
payerId = AccountId.fromString(payerStr);
|
|
31
|
+
}
|
|
32
|
+
else {
|
|
33
|
+
const evmAddress = pk.publicKey.toEvmAddress();
|
|
34
|
+
payerId = AccountId.fromEvmAddress(0, 0, evmAddress);
|
|
35
|
+
}
|
|
36
|
+
const recipientId = resolvePayTo(paymentRequirements.payTo);
|
|
37
|
+
// Convert EVM asset address to Hedera token ID
|
|
38
|
+
const tokenEntityNum = parseInt(paymentRequirements.asset.replace(/^0x/, ''), 16);
|
|
39
|
+
const tokenId = TokenId.fromString(`0.0.${tokenEntityNum}`);
|
|
40
|
+
const amount = Number(paymentRequirements.maxAmountRequired);
|
|
41
|
+
// Facilitator fee payer generates the TX ID (pays HBAR gas)
|
|
42
|
+
const feePayerAccountId = facilitatorFeePayer
|
|
43
|
+
? AccountId.fromString(facilitatorFeePayer)
|
|
44
|
+
: payerId;
|
|
45
|
+
const client = network === 'testnet' ? Client.forTestnet() : Client.forMainnet();
|
|
46
|
+
const txId = TransactionId.withValidStart(feePayerAccountId, Timestamp.generate());
|
|
47
|
+
const tx = new TransferTransaction()
|
|
48
|
+
.addTokenTransfer(tokenId, payerId, -amount)
|
|
49
|
+
.addTokenTransfer(tokenId, recipientId, amount)
|
|
50
|
+
.setTransactionId(txId)
|
|
51
|
+
.setMaxTransactionFee(2_000_000)
|
|
52
|
+
.setTransactionValidDuration(180);
|
|
53
|
+
// Freeze and partially sign with payer's key only
|
|
54
|
+
const frozenTx = tx.freezeWith(client);
|
|
55
|
+
const signedTx = await frozenTx.sign(pk);
|
|
56
|
+
const txBytes = signedTx.toBytes();
|
|
57
|
+
// Blocky402 expects: { x402Version, payload: { transaction } }
|
|
58
|
+
// Do NOT include scheme/network in the outer object
|
|
59
|
+
const payload = {
|
|
60
|
+
x402Version: 1,
|
|
61
|
+
payload: {
|
|
62
|
+
transaction: Buffer.from(txBytes).toString('base64'),
|
|
63
|
+
},
|
|
64
|
+
};
|
|
65
|
+
client.close();
|
|
66
|
+
return Buffer.from(JSON.stringify(payload)).toString('base64');
|
|
67
|
+
}
|
|
68
|
+
//# sourceMappingURL=hedera-payment.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hedera-payment.js","sourceRoot":"","sources":["../../src/client/hedera-payment.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { Client as MCPClient } from '@modelcontextprotocol/sdk/client/index.js';
|
|
2
|
+
import type { RequestOptions } from '@modelcontextprotocol/sdk/shared/protocol.js';
|
|
3
|
+
import type { CallToolRequest, CallToolResult, CallToolResultSchema, CompatibilityCallToolResultSchema } from '@modelcontextprotocol/sdk/types.js';
|
|
4
|
+
import type { MultiNetworkSigner, PaymentRequirements, Network } from 'x402/types';
|
|
5
|
+
import { type HederaPaymentConfig } from './hedera-payment.js';
|
|
6
|
+
export interface X402AugmentedClient {
|
|
7
|
+
callTool(params: CallToolRequest["params"], resultSchema?: typeof CallToolResultSchema | typeof CompatibilityCallToolResultSchema, options?: RequestOptions): Promise<CallToolResult>;
|
|
8
|
+
}
|
|
9
|
+
export type X402ClientConfig = {
|
|
10
|
+
wallet: Partial<MultiNetworkSigner>;
|
|
11
|
+
maxPaymentValue?: bigint;
|
|
12
|
+
version?: number;
|
|
13
|
+
/** Hedera-specific config for native HTS payment signing */
|
|
14
|
+
hederaConfig?: HederaPaymentConfig;
|
|
15
|
+
confirmationCallback?: (payment: PaymentRequirements[]) => Promise<boolean | number | {
|
|
16
|
+
index: number;
|
|
17
|
+
} | {
|
|
18
|
+
network: Network;
|
|
19
|
+
} | {
|
|
20
|
+
requirement: PaymentRequirements;
|
|
21
|
+
}>;
|
|
22
|
+
};
|
|
23
|
+
/**
|
|
24
|
+
* Wraps an MCP client with X402 payment capabilities (Hedera-only)
|
|
25
|
+
*/
|
|
26
|
+
export declare function withX402Client<T extends MCPClient>(client: T, x402Config: X402ClientConfig): X402AugmentedClient & T;
|
|
27
|
+
//# sourceMappingURL=with-x402-client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"with-x402-client.d.ts","sourceRoot":"","sources":["../../src/client/with-x402-client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,IAAI,SAAS,EAAE,MAAM,2CAA2C,CAAC;AACrF,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,8CAA8C,CAAC;AACnF,OAAO,KAAK,EACR,eAAe,EACf,cAAc,EACd,oBAAoB,EACpB,iCAAiC,EACpC,MAAM,oCAAoC,CAAC;AAE5C,OAAO,KAAK,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AACnF,OAAO,EAA6B,KAAK,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAI1F,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CACN,MAAM,EAAE,eAAe,CAAC,QAAQ,CAAC,EACjC,YAAY,CAAC,EACT,OAAO,oBAAoB,GAC3B,OAAO,iCAAiC,EAC5C,OAAO,CAAC,EAAE,cAAc,GACvB,OAAO,CAAC,cAAc,CAAC,CAAC;CAC5B;AAED,MAAM,MAAM,gBAAgB,GAAG;IAC7B,MAAM,EAAE,OAAO,CAAC,kBAAkB,CAAC,CAAC;IACpC,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,4DAA4D;IAC5D,YAAY,CAAC,EAAE,mBAAmB,CAAC;IACnC,oBAAoB,CAAC,EAAE,CAAC,OAAO,EAAE,mBAAmB,EAAE,KAAK,OAAO,CAC9D,OAAO,GACP,MAAM,GACN;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE,GACjB;QAAE,OAAO,EAAE,OAAO,CAAA;KAAE,GACpB;QAAE,WAAW,EAAE,mBAAmB,CAAA;KAAE,CACvC,CAAC;CACH,CAAC;AAKF;;GAEG;AACH,wBAAgB,cAAc,CAAC,CAAC,SAAS,SAAS,EAChD,MAAM,EAAE,CAAC,EACT,UAAU,EAAE,gBAAgB,GAC3B,mBAAmB,GAAG,CAAC,CA2KzB"}
|