@agentgrant.cash/cli 1.0.1 → 1.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/.env.example CHANGED
@@ -3,21 +3,21 @@
3
3
  # Copy to `.env` in the folder you run the CLI from (the current working
4
4
  # directory). The CLI loads it automatically — this is how you point an
5
5
  # installed / `npx` CLI at localhost or staging. Already-exported shell env vars
6
- # take precedence over the file. Every value is optional; the defaults point at
7
- # production. The active backend is shown by `grant status`.
6
+ # take precedence over the file. Every value is optional; the built-in defaults
7
+ # point at the DEVELOP environment. The active backend is shown by `grant config
8
+ # show` / `grant status`.
8
9
  #
9
10
  # Example (local dev):
10
11
  # GRANTCASH_API_URL=http://localhost:3001/api
11
12
  # GRANTCASH_AGENT_URL=http://localhost:8080
12
13
 
13
- # ── Money side (Perfolio backend — gold, portfolio, cash) ──
14
- GRANTCASH_API_URL=https://api.perfolio.ai/api
15
- GRANTCASH_FIAT_URL=https://api-fiat.perfolio.ai/api
16
- GRANTCASH_APP_URL=https://app.perfolio.ai
14
+ # ── Money side (Perfolio backend — gold, portfolio, cash) ── [develop defaults]
15
+ GRANTCASH_API_URL=https://api-dev.perfolio.ai/api
16
+ GRANTCASH_FIAT_URL=https://api-dev-fiat.perfolio.ai/api
17
+ GRANTCASH_APP_URL=https://grant-cash-app-production.up.railway.app
17
18
 
18
- # ── Agent side (Agent-mode backend — pay-per-use services, x402) ──
19
- # Set this to wherever the agent-mode backend lives (placeholder default).
20
- GRANTCASH_AGENT_URL=https://api-agent.perfolio.ai
19
+ # ── Agent side (Agent-mode backend — pay-per-use services, x402) ── [develop]
20
+ GRANTCASH_AGENT_URL=https://agent-mode-backend-develop.up.railway.app
21
21
 
22
22
  # ── Misc ──
23
23
  # Override the merged credentials file (default ~/.grant-cash/credentials.json).
package/dist/cli/index.js CHANGED
@@ -37,6 +37,7 @@ import { registerAccount } from "./perfolio-commands/account.js";
37
37
  import { registerTx } from "./perfolio-commands/tx.js";
38
38
  import { registerSession } from "./perfolio-commands/session.js";
39
39
  import { registerLoans } from "./perfolio-commands/loans.js";
40
+ import { registerSpending } from "./perfolio-commands/spending.js";
40
41
  let version = "0.0.0";
41
42
  try {
42
43
  version =
@@ -66,6 +67,7 @@ registerEarn(program);
66
67
  registerHyperliquid(program);
67
68
  registerPolymarket(program);
68
69
  registerLoans(program);
70
+ registerSpending(program);
69
71
  registerAccount(program);
70
72
  registerTx(program);
71
73
  registerSession(program);
@@ -0,0 +1,57 @@
1
+ import { buildCtx, requireAuth, out, fail, resolveCash } from '../money-helpers.js';
2
+ import { describeCashResolution } from '../../lib/index.js';
3
+ import { waitForTx } from '../../lib/verify.js';
4
+ /**
5
+ * Spending account — the agent's pay-per-use balance (USDC on Base). It is
6
+ * funded by bridging cash out of the main account, mirroring the other
7
+ * account-to-account transfers already in the CLI:
8
+ * - cash ↔ trading → `hl deposit` / `hl withdraw`
9
+ * - cash ↔ predictions → `polymarket deposit` / `polymarket withdraw`
10
+ * - cash → spending → `spending deposit` (this file)
11
+ *
12
+ * The reverse (spending → cash) has NO backend route — the spending balance is
13
+ * receive-only, exactly as in the web app (AccountTransferFlow) — so we offer
14
+ * only the inbound transfer and don't fabricate a withdraw.
15
+ */
16
+ export function registerSpending(program) {
17
+ const spending = program
18
+ .command('spending')
19
+ .description('Your agent spending account (pay-per-use balance)');
20
+ spending
21
+ .command('deposit')
22
+ .alias('add')
23
+ .alias('top-up')
24
+ .description('Move cash from your account into your agent spending balance (autonomous — no browser)')
25
+ .requiredOption('--amount <amount>', 'cash to move into spending — in your display currency by default; prefix $/₹ to force one, or pass --usd')
26
+ .option('--usd', 'interpret --amount as US dollars, ignoring your display currency')
27
+ .option('--no-wait', 'return immediately without waiting for the bridge tx to confirm')
28
+ .action(async (opts, cmd) => {
29
+ const ctx = buildCtx(cmd);
30
+ requireAuth(ctx);
31
+ // Autonomous: POST /tx/bridge-base builds the USDT-approve + Across bridge
32
+ // (ETH USDT → Base USDC) and executes them via the Biconomy session grant
33
+ // (agent-signed) — no browser. Two-stage settlement, same as `hl deposit`:
34
+ // the bridge tx confirms the Ethereum leg, but Across fills onto Base a few
35
+ // MINUTES later. So a confirmed tx means the funds are on their way, NOT
36
+ // yet spendable — we confirm the tx and say so honestly (no false "done").
37
+ const m = await resolveCash(ctx, opts.amount, 6, { usd: !!opts.usd });
38
+ const wait = opts.wait !== false;
39
+ const label = `Move ${describeCashResolution(m)} cash → spending`;
40
+ const res = await ctx.client.bridgeToBase({ amountUsdt: m.usdString });
41
+ const txHash = res?.txHash;
42
+ const tail = txHash ? ` (tx ${txHash})` : '';
43
+ if (!wait) {
44
+ out(ctx, `Submitted: ${label}${tail}.\nFunds arrive in your spending balance a few minutes after the bridge tx confirms — check \`grant portfolio\`.`, { submitted: true, confirmed: false, status: res?.status ?? 'submitted', txHash, quote: res?.quote });
45
+ return;
46
+ }
47
+ const txResult = await waitForTx(ctx.client, txHash);
48
+ if (txResult.status === 'failed')
49
+ fail(`${label} failed on-chain${tail}.`, ctx.json);
50
+ if (txResult.status === 'success') {
51
+ out(ctx, `✓ ${label}: bridge tx confirmed${tail}. Your spending balance updates in a few minutes once the funds land on Base — check \`grant portfolio\`.`, { submitted: true, confirmed: true, settledOnBase: false, status: 'success', txHash, quote: res?.quote });
52
+ }
53
+ else {
54
+ out(ctx, `${label}: submitted${tail} but not yet confirmed. Re-check with \`grant tx status${txHash ? ` ${txHash}` : ''}\`.`, { submitted: true, confirmed: false, settledOnBase: false, status: txResult.status, txHash, quote: res?.quote });
55
+ }
56
+ });
57
+ }
@@ -260,6 +260,19 @@ export class PerfolioClient {
260
260
  * so its "submitted" was a false positive that moved no funds.)
261
261
  */
262
262
  hlDeposit(b) { return this.post(this.urls.api, '/tx/bridge-deposit', b); }
263
+ /**
264
+ * Autonomous cash → spending bridge. Hits POST /tx/bridge-base, which builds
265
+ * the USDT-approve + Across bridge (ETH USDT → Base USDC) and executes them via
266
+ * the Biconomy defi session grant (agent-signed) — no user signature, no
267
+ * browser. Funds the Grant Cash agent's USDC spending balance on Base. A
268
+ * returned txHash means the Ethereum leg was SUBMITTED; the spending balance
269
+ * updates on Base a few minutes later once Across fills. Mirrors hlDeposit
270
+ * (/tx/bridge-deposit) — same Across Swap API + session execution; only the
271
+ * destination (Base 8453) and output token (USDC) differ.
272
+ */
273
+ bridgeToBase(b) {
274
+ return this.post(this.urls.api, '/tx/bridge-base', b);
275
+ }
263
276
  /** Autonomous HL → Ethereum withdrawal (server-signs via Privy; no browser). */
264
277
  hlWithdraw(b) {
265
278
  return this.post(this.urls.api, '/hl/withdraw-to-evm/execute', b);
@@ -2,19 +2,18 @@ import { homedir } from "node:os";
2
2
  import { join, dirname } from "node:path";
3
3
  import { mkdirSync, readFileSync, writeFileSync, unlinkSync } from "node:fs";
4
4
  /**
5
- * Backend base URLs — env-overridable, production defaults.
6
- *
7
- * Money side = Perfolio backend; Agent side = Agent-mode backend. Set the env
8
- * vars (in a `.env` in the directory you run the CLI from, or as exported shell
9
- * vars) to repoint at dev/staging/localhost without touching code. The active
10
- * backend is shown in `grant status`.
5
+ * Backend base URLs — env-overridable. Defaults point at the DEVELOP environment
6
+ * (this is an internal/testing CLI for now). Set the env vars (in a `.env` in the
7
+ * directory you run the CLI from, or as exported shell vars) to repoint at
8
+ * localhost/staging/production without touching code. The active backend is shown
9
+ * by `grant config show` / `grant status`.
11
10
  */
12
11
  export function baseUrls(env = process.env) {
13
12
  return {
14
- api: env.GRANTCASH_API_URL || "https://api.perfolio.ai/api",
15
- fiat: env.GRANTCASH_FIAT_URL || "https://api-fiat.perfolio.ai/api",
16
- app: env.GRANTCASH_APP_URL || "https://app.perfolio.ai",
17
- agent: env.GRANTCASH_AGENT_URL || "https://api-agent.perfolio.ai",
13
+ api: env.GRANTCASH_API_URL || "https://api-dev.perfolio.ai/api",
14
+ fiat: env.GRANTCASH_FIAT_URL || "https://api-dev-fiat.perfolio.ai/api",
15
+ app: env.GRANTCASH_APP_URL || "https://grant-cash-app-production.up.railway.app",
16
+ agent: env.GRANTCASH_AGENT_URL || "https://agent-mode-backend-develop.up.railway.app",
18
17
  };
19
18
  }
20
19
  export function resolveCredsPath(flag, env = process.env) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agentgrant.cash/cli",
3
- "version": "1.0.1",
3
+ "version": "1.1.0",
4
4
  "description": "Grant Cash — one CLI for your money (gold) and your agent (pay-per-use services). Routes to the Perfolio backend and the Agent-mode backend behind a single, plain-language surface.",
5
5
  "type": "module",
6
6
  "bin": {