@clawcard/cli 3.2.1 → 3.2.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/package.json +1 -1
- package/skill/SKILL.md +31 -6
- package/src/agent-api.js +10 -0
- package/src/commands/agent.js +85 -5
- package/src/index.js +16 -27
package/package.json
CHANGED
package/skill/SKILL.md
CHANGED
|
@@ -98,11 +98,15 @@ Close card:
|
|
|
98
98
|
clawcard agent cards close <card-id> --json
|
|
99
99
|
```
|
|
100
100
|
|
|
101
|
-
## Stablecoin Wallet (USDC on Base)
|
|
101
|
+
## Stablecoin Wallet (USDC + pathUSD on Base)
|
|
102
102
|
|
|
103
|
-
Your agent
|
|
103
|
+
Your agent has a wallet on Base with three balances:
|
|
104
104
|
|
|
105
|
-
**
|
|
105
|
+
- **ETH** — gas fees (needed for on-chain transactions)
|
|
106
|
+
- **USDC** — x402 protocol payments and direct transfers
|
|
107
|
+
- **pathUSD** — MPP (Machine Payments Protocol) payments via Tempo/Stripe
|
|
108
|
+
|
|
109
|
+
**Use wallet for:** x402 APIs (HTTP 402 responses), MPP services, crypto transfers, micropayments
|
|
106
110
|
**Use cards for:** traditional merchant checkouts, websites with payment forms
|
|
107
111
|
|
|
108
112
|
### Setup
|
|
@@ -116,7 +120,7 @@ If you get `"No wallet found"`, create one via the API or run `clawcard agent wa
|
|
|
116
120
|
|
|
117
121
|
### Commands
|
|
118
122
|
|
|
119
|
-
Check balance (shows USDC
|
|
123
|
+
Check balance (shows ETH, USDC, and pathUSD balances):
|
|
120
124
|
```
|
|
121
125
|
clawcard agent wallet balance --json
|
|
122
126
|
```
|
|
@@ -131,21 +135,42 @@ Pay a URL via x402 (default — when a service returns HTTP 402):
|
|
|
131
135
|
clawcard agent wallet send --url https://api.example.com/data --json
|
|
132
136
|
```
|
|
133
137
|
|
|
134
|
-
Pay a URL via MPP (Machine Payments Protocol — Stripe/Tempo):
|
|
138
|
+
Pay a URL via MPP (Machine Payments Protocol — Stripe/Tempo, uses pathUSD):
|
|
135
139
|
```
|
|
136
140
|
clawcard agent wallet send --url https://api.example.com/data --protocol mpp --json
|
|
137
141
|
```
|
|
138
142
|
|
|
143
|
+
**Explorer links:** Payment responses include explorer URLs. x402 transactions link to Basescan (`basescan.org/tx/...`), MPP and bridge transactions link to Tempo Explorer (`explore.tempo.xyz/receipt/...`).
|
|
144
|
+
|
|
139
145
|
View transaction history:
|
|
140
146
|
```
|
|
141
147
|
clawcard agent wallet transactions --json
|
|
142
148
|
```
|
|
143
149
|
|
|
144
|
-
Fund
|
|
150
|
+
### Fund Wizard (3 options)
|
|
151
|
+
|
|
152
|
+
The fund command is a wizard with three funding options:
|
|
153
|
+
|
|
154
|
+
1. **Gas fees (ETH)** — opens Coinbase Onramp to buy ETH (needed for on-chain transactions)
|
|
155
|
+
2. **x402 services (USDC)** — opens Coinbase Onramp to buy USDC (for x402 protocol payments)
|
|
156
|
+
3. **MPP services (pathUSD)** — bridges USDC from your existing balance to pathUSD on Tempo (for MPP payments)
|
|
157
|
+
|
|
158
|
+
Fund your wallet interactively (runs the wizard):
|
|
159
|
+
```
|
|
160
|
+
clawcard agent wallet fund
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
Fund via JSON (opens Coinbase Onramp for USDC/ETH):
|
|
145
164
|
```
|
|
146
165
|
clawcard agent wallet fund --amount 10.00 --json
|
|
147
166
|
```
|
|
148
167
|
|
|
168
|
+
### Bridge USDC to pathUSD
|
|
169
|
+
|
|
170
|
+
To pay for MPP services, you need pathUSD. The fund wizard's "MPP services" option converts USDC from your wallet balance to pathUSD on Tempo. This is a bridge operation (USDC on Base -> pathUSD on Tempo).
|
|
171
|
+
|
|
172
|
+
The bridge response includes both a Basescan link (Base transaction) and a Tempo Explorer link (Tempo receipt).
|
|
173
|
+
|
|
149
174
|
Or send USDC directly to your wallet address on Base. Check your address with `clawcard agent wallet --json`.
|
|
150
175
|
|
|
151
176
|
## Discover Services
|
package/src/agent-api.js
CHANGED
|
@@ -177,3 +177,13 @@ export const registerOnChainIdentity = (agentId, data = {}) =>
|
|
|
177
177
|
// A2A Agent Card
|
|
178
178
|
export const getAgentCard = (agentId) =>
|
|
179
179
|
agentRequest(`/api/agents/${agentId}/agent-card`);
|
|
180
|
+
|
|
181
|
+
// Card access
|
|
182
|
+
export const getCardAccess = () =>
|
|
183
|
+
agentRequest("/api/cards-access");
|
|
184
|
+
|
|
185
|
+
export const requestCardAccess = (data) =>
|
|
186
|
+
agentRequest("/api/cards-access", {
|
|
187
|
+
method: "POST",
|
|
188
|
+
body: JSON.stringify(data),
|
|
189
|
+
});
|
package/src/commands/agent.js
CHANGED
|
@@ -23,6 +23,7 @@ import {
|
|
|
23
23
|
walletSend,
|
|
24
24
|
walletTransactions as walletTransactionsApi,
|
|
25
25
|
discoverServices,
|
|
26
|
+
requestCardAccess,
|
|
26
27
|
getOnChainIdentity,
|
|
27
28
|
registerOnChainIdentity,
|
|
28
29
|
getAgentCard,
|
|
@@ -183,13 +184,92 @@ export async function agentCardsCmd(options) {
|
|
|
183
184
|
console.log();
|
|
184
185
|
}
|
|
185
186
|
|
|
187
|
+
export async function agentCardsRequestCmd(options) {
|
|
188
|
+
if (options.json) {
|
|
189
|
+
try {
|
|
190
|
+
const result = await requestCardAccess({});
|
|
191
|
+
return output(result, true);
|
|
192
|
+
} catch (err) {
|
|
193
|
+
return output({ error: err.message }, true);
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
const prompts = await import("@clack/prompts");
|
|
198
|
+
|
|
199
|
+
console.log();
|
|
200
|
+
console.log(` ${orange.bold("Request Virtual Card Access")}`);
|
|
201
|
+
console.log();
|
|
202
|
+
console.log(chalk.dim(" Virtual cards let your agent make purchases on traditional websites."));
|
|
203
|
+
console.log(chalk.dim(" We review requests to ensure compliance. Usually approved within 24 hours."));
|
|
204
|
+
console.log();
|
|
205
|
+
|
|
206
|
+
const country = await prompts.text({
|
|
207
|
+
message: "What country are you based in?",
|
|
208
|
+
placeholder: "United States",
|
|
209
|
+
validate: (v) => { if (!v?.trim()) return "Required"; },
|
|
210
|
+
});
|
|
211
|
+
if (prompts.isCancel(country)) return;
|
|
212
|
+
|
|
213
|
+
const useCase = await prompts.text({
|
|
214
|
+
message: "What will your agent use cards for?",
|
|
215
|
+
placeholder: "Buying domains, hosting, SaaS subscriptions",
|
|
216
|
+
validate: (v) => { if (!v?.trim()) return "Required"; },
|
|
217
|
+
});
|
|
218
|
+
if (prompts.isCancel(useCase)) return;
|
|
219
|
+
|
|
220
|
+
const company = await prompts.text({
|
|
221
|
+
message: "Company or project name (optional)",
|
|
222
|
+
placeholder: "My AI Startup",
|
|
223
|
+
});
|
|
224
|
+
if (prompts.isCancel(company)) return;
|
|
225
|
+
|
|
226
|
+
const s = prompts.spinner();
|
|
227
|
+
s.start("Submitting request...");
|
|
228
|
+
|
|
229
|
+
try {
|
|
230
|
+
const result = await requestCardAccess({
|
|
231
|
+
country,
|
|
232
|
+
useCase,
|
|
233
|
+
company: company || "",
|
|
234
|
+
});
|
|
235
|
+
|
|
236
|
+
if (result.alreadyApproved) {
|
|
237
|
+
s.stop(chalk.green("You're already approved! Create cards with: clawcard agent cards create"));
|
|
238
|
+
} else {
|
|
239
|
+
s.stop(chalk.green("Request submitted!"));
|
|
240
|
+
console.log();
|
|
241
|
+
console.log(` ${result.message}`);
|
|
242
|
+
console.log(chalk.dim(" Questions? team@clawcard.dev"));
|
|
243
|
+
}
|
|
244
|
+
} catch (err) {
|
|
245
|
+
s.stop("Failed");
|
|
246
|
+
console.log(` Error: ${err.message}`);
|
|
247
|
+
}
|
|
248
|
+
console.log();
|
|
249
|
+
}
|
|
250
|
+
|
|
186
251
|
export async function agentCardsCreateCmd(options) {
|
|
187
252
|
const agentId = await getAgentId();
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
253
|
+
let result;
|
|
254
|
+
try {
|
|
255
|
+
result = await createCard(agentId, {
|
|
256
|
+
amountCents: parseInt(options.amount),
|
|
257
|
+
type: options.type,
|
|
258
|
+
memo: options.memo || "Agent card",
|
|
259
|
+
});
|
|
260
|
+
} catch (err) {
|
|
261
|
+
if (err.message?.includes("approval") || err.message?.includes("needsApproval")) {
|
|
262
|
+
if (options.json) return output({ error: "Card access not approved. Run: clawcard agent cards request", needsApproval: true }, true);
|
|
263
|
+
console.log();
|
|
264
|
+
console.log(` ${orange("Virtual cards require approval.")}`);
|
|
265
|
+
console.log(` Run: ${chalk.bold("clawcard agent cards request")}`);
|
|
266
|
+
console.log();
|
|
267
|
+
return;
|
|
268
|
+
}
|
|
269
|
+
if (options.json) return output({ error: err.message }, true);
|
|
270
|
+
console.log(` Error: ${err.message}`);
|
|
271
|
+
return;
|
|
272
|
+
}
|
|
193
273
|
if (options.json) return output(result, true);
|
|
194
274
|
|
|
195
275
|
console.log();
|
package/src/index.js
CHANGED
|
@@ -169,6 +169,14 @@ agentCards
|
|
|
169
169
|
const { agentCardsCmd } = await import("./commands/agent.js");
|
|
170
170
|
await agentCardsCmd(options);
|
|
171
171
|
});
|
|
172
|
+
agentCards
|
|
173
|
+
.command("request")
|
|
174
|
+
.description("Request access to virtual cards")
|
|
175
|
+
.option("--json", "Output as JSON")
|
|
176
|
+
.action(async (options) => {
|
|
177
|
+
const { agentCardsRequestCmd } = await import("./commands/agent.js");
|
|
178
|
+
await agentCardsRequestCmd(options);
|
|
179
|
+
});
|
|
172
180
|
agentCards
|
|
173
181
|
.command("create")
|
|
174
182
|
.requiredOption("--amount <cents>", "Spend limit in cents")
|
|
@@ -489,49 +497,30 @@ if (process.argv.length <= 2) {
|
|
|
489
497
|
];
|
|
490
498
|
} else {
|
|
491
499
|
// Check user state to show contextual nudges
|
|
492
|
-
let hasBalance = true;
|
|
493
500
|
let hasAgent = true;
|
|
494
501
|
|
|
495
502
|
try {
|
|
496
|
-
const {
|
|
497
|
-
const
|
|
498
|
-
getBalance().catch(() => ({ amountCents: 0 })),
|
|
499
|
-
listAgents().catch(() => []),
|
|
500
|
-
]);
|
|
501
|
-
hasBalance = balance.amountCents >= 500;
|
|
503
|
+
const { listAgents } = await import("./api.js");
|
|
504
|
+
const agents = await listAgents().catch(() => []);
|
|
502
505
|
hasAgent = agents.some((a) => a.status === "active");
|
|
503
506
|
} catch {
|
|
504
507
|
// couldn't check — show full menu
|
|
505
508
|
}
|
|
506
509
|
|
|
507
|
-
if (!
|
|
508
|
-
p.log.warn(
|
|
509
|
-
`Account balance is under $5. Run ${orange("clawcard billing topup")} to add funds.`
|
|
510
|
-
);
|
|
511
|
-
}
|
|
512
|
-
|
|
513
|
-
if (!hasAgent && !hasBalance) {
|
|
510
|
+
if (!hasAgent) {
|
|
514
511
|
p.log.info(
|
|
515
|
-
|
|
516
|
-
);
|
|
517
|
-
} else if (!hasAgent) {
|
|
518
|
-
p.log.warn(
|
|
519
|
-
`You have balance but no agent yet. Run ${orange("clawcard keys create")} to create one.`
|
|
512
|
+
`No agent yet. Run ${orange("clawcard keys create")} to create one.`
|
|
520
513
|
);
|
|
521
514
|
}
|
|
522
515
|
|
|
523
516
|
options = [
|
|
524
517
|
...(hasAgent
|
|
525
518
|
? [
|
|
526
|
-
{ value: "agent", label: "View agent details", hint: "phone, email, budget" },
|
|
527
|
-
{ value: "agent-fund", label: "Fund my agent", hint: "allocate budget from your balance" },
|
|
519
|
+
{ value: "agent", label: "View agent details", hint: "phone, email, wallet, budget" },
|
|
528
520
|
{ value: "setup", label: "Configure", hint: "install skill for your agent" },
|
|
529
521
|
]
|
|
530
|
-
:
|
|
531
|
-
|
|
532
|
-
: []),
|
|
533
|
-
{ value: "topup", label: "Top up my account", hint: "add balance (10% fee)" },
|
|
534
|
-
{ value: "referral", label: "Referral", hint: "share & earn $5" },
|
|
522
|
+
: [{ value: "keys-create", label: "Create agent", hint: "create your first agent" }]),
|
|
523
|
+
{ value: "topup", label: "Top up account", hint: "add balance for virtual cards (10% fee)" },
|
|
535
524
|
{ value: "settings", label: "Settings", hint: "billing address & preferences" },
|
|
536
525
|
{ value: "whoami", label: "Who am I?", hint: "show current account" },
|
|
537
526
|
{ value: "dashboard", label: "Open dashboard", hint: "open in browser" },
|
|
@@ -555,7 +544,7 @@ if (process.argv.length <= 2) {
|
|
|
555
544
|
signup: () => import("./commands/signup.js").then((m) => m.signupCommand()),
|
|
556
545
|
logout: () => import("./commands/logout.js").then((m) => m.logoutCommand()),
|
|
557
546
|
whoami: () => import("./commands/whoami.js").then((m) => m.whoamiCommand()),
|
|
558
|
-
agent: () => import("./commands/
|
|
547
|
+
agent: () => import("./commands/agent.js").then((m) => m.agentInfoCmd({})),
|
|
559
548
|
"agent-fund": () => import("./commands/keys.js").then((m) => m.agentFundCommand()),
|
|
560
549
|
"keys-create": () => import("./commands/keys.js").then((m) => m.keysCreateCommand()),
|
|
561
550
|
"topup": () => import("./commands/billing.js").then((m) => m.billingTopupCommand()),
|