@fastxyz/cli 1.0.2 → 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/README.md CHANGED
@@ -32,11 +32,18 @@ fast account create
32
32
  # Check balances
33
33
  fast info balance
34
34
 
35
- # Send USDC
35
+ # Send the network's default token (fastUSD on mainnet) — Fast → Fast
36
36
  fast send fast1abc...xyz 10
37
37
 
38
- # Bridge from Arbitrum Sepolia to Fast
39
- fast fund crypto 50 --chain arbitrum-sepolia
38
+ # Send a specific token explicitly
39
+ fast send fast1abc...xyz 10 --token USDC
40
+
41
+ # Bridge USDC from Arbitrum Sepolia to Fast (--token USDC is required on
42
+ # mainnet because the network default — fastUSD — is not on EVM chains)
43
+ fast fund usdc crypto 50 --chain arbitrum-sepolia --token USDC
44
+
45
+ # Or get a unified Fast web-app URL to fund fastUSD (mainnet only)
46
+ fast fund fastusd --amount 50
40
47
 
41
48
  # Pay an x402-protected API
42
49
  fast pay https://api.example.com/resource
@@ -73,6 +80,32 @@ These options work with every command:
73
80
  | `--non-interactive` | Auto-confirm confirmations and fail when required input is missing |
74
81
  | `--debug` | Enable verbose debug logging to stderr |
75
82
 
83
+ ### Default token
84
+
85
+ Commands that accept `--token` (currently `fast send` and `fast fund usdc
86
+ crypto`) default to the active network's `defaultToken.symbol` when the flag
87
+ is omitted: `fastUSD` on mainnet, `testUSDC` on testnet. Bridge routes
88
+ additionally require the resolved token to exist on the target chain — on
89
+ mainnet bridges you must pass `--token USDC` explicitly because `fastUSD` does
90
+ not exist on EVM chains.
91
+
92
+ To customize the default, register a network with `fast network add <name>
93
+ --config <path>` where the JSON config includes a `defaultToken` field, for
94
+ example:
95
+
96
+ ```json
97
+ {
98
+ "defaultToken": {
99
+ "symbol": "USDC",
100
+ "tokenId": "0x...",
101
+ "decimals": 6
102
+ }
103
+ }
104
+ ```
105
+
106
+ If a custom network omits `defaultToken`, callers must pass `--token`
107
+ explicitly; otherwise the command errors with `INVALID_USAGE`.
108
+
76
109
  ## Commands
77
110
 
78
111
  ### `fast account create`
@@ -98,6 +131,7 @@ fast account import --name my-imported-account --private-key 0x...
98
131
  ```
99
132
 
100
133
  **Options:**
134
+
101
135
  - `--name <alias>` — Optional human-readable alias for the imported account
102
136
  - `--private-key <hex>` — Hex-encoded 32-byte private key
103
137
  - `--key-file <path>` — Path to a JSON file containing a `privateKey` field
@@ -157,13 +191,15 @@ fast send fast1recipient... 10.5 --token USDC
157
191
  ```
158
192
 
159
193
  **Positional arguments:**
194
+
160
195
  - `<address>` — Recipient address (`fast1...` for Fast, `0x...` for EVM)
161
196
  - `<amount>` — Human-readable amount (for example, `10` or `1.5`)
162
197
 
163
198
  **Options:**
199
+
164
200
  - `--from-chain <chain>` — Source EVM chain for EVM → Fast transfers
165
201
  - `--to-chain <chain>` — Destination EVM chain for Fast → EVM transfers
166
- - `--token <token>` — Token symbol or token ID (defaults to the first configured bridge token, typically `USDC`)
202
+ - `--token <token>` — Token symbol or token ID. Defaults to the network's `defaultToken.symbol` (`fastUSD` on mainnet, `testUSDC` on testnet). Bridge routes require the resolved token to be available on the target chain; otherwise the command errors with `CommandUnsupportedForTokenError`.
167
203
  - `--eip-7702` — Use the smart deposit flow for EVM → Fast transfers
168
204
  - `--account <name>` — Sender account (defaults to the configured default)
169
205
 
@@ -212,6 +248,7 @@ fast info history --from fast1... --limit 20
212
248
  ```
213
249
 
214
250
  **Options:**
251
+
215
252
  - `--from <address>` — Filter by sender address
216
253
  - `--to <address>` — Filter by recipient address
217
254
  - `--token <token>` — Filter by token name or token ID
@@ -240,39 +277,152 @@ fast info bridge-tokens
240
277
 
241
278
  ---
242
279
 
243
- ### `fast fund fiat`
280
+ ### `fast fund usdc fiat`
244
281
 
245
- Get a fiat on-ramp URL for funding a Fast address.
282
+ Get a fiat on-ramp URL for funding a Fast address with USDC. The URL targets
283
+ [ramp.fast.xyz](https://ramp.fast.xyz); the deposit lands on Fast as bridged
284
+ USDC, distinct from the Fast-native `fastUSD`.
246
285
 
247
286
  ```bash
248
- fast fund fiat --network mainnet
287
+ fast fund usdc fiat --network mainnet
249
288
  ```
250
289
 
251
290
  **Requirements:**
252
- - Only available on `mainnet`
253
- - Prints a funding URL for you to open in your browser
254
291
 
255
- **Options:**
256
- - `--address <fast-address>` Fund a specific Fast address directly (otherwise uses the selected account)
257
- - `--network <name>` — Must be `mainnet`
292
+ - Mainnet only (Ramp does not support testnet).
293
+ - Active account or `--address <fast1...>`.
258
294
 
259
295
  ---
260
296
 
261
- ### `fast fund crypto <amount>`
297
+ ### `fast fund usdc crypto <amount>`
262
298
 
263
- Bridge crypto from an EVM chain to the Fast network.
299
+ Bridge USDC from an EVM chain to the Fast network. The deposit lands as
300
+ bridged USDC on Fast (distinct from `fastUSD`).
264
301
 
265
302
  ```bash
266
- fast fund crypto 10.5 --chain arbitrum-sepolia --token USDC
303
+ fast fund usdc crypto 10.5 --chain arbitrum-sepolia --token USDC
267
304
  ```
268
305
 
269
306
  **Positional arguments:**
270
- - `<amount>` — Human-readable amount
307
+
308
+ - `<amount>` — Human-readable amount to bridge (e.g., `10.5`).
309
+
310
+ **Options:**
311
+
312
+ - `--chain <chain>` — Source EVM chain (required).
313
+ - `--token <token>` — Token symbol or token ID. Defaults to the network's `defaultToken.symbol`. On mainnet that's `fastUSD`, which is **not** on EVM chains — pass `--token USDC` explicitly for the bridge case, or the command errors with `CommandUnsupportedForTokenError`.
314
+ - `--eip-7702` — Use the smart deposit flow (gas paid in USDC via paymaster).
315
+
316
+ ---
317
+
318
+ ### `fast fund fastusd`
319
+
320
+ Print an `app.fast.xyz/send` URL that opens the unified Fast web app to fund
321
+ your account with **fastUSD** (a Fast-native token, separate from bridged USDC).
322
+ The web app handles fiat-onramp, crypto-bridge, and wallet-to-wallet funding
323
+ under the hood; the CLI's job is just to produce the URL.
324
+
325
+ ```bash
326
+ fast fund fastusd
327
+ # → https://app.fast.xyz/send?to=fast1...
328
+
329
+ fast fund fastusd --amount 25
330
+ # → https://app.fast.xyz/send?to=fast1...&amount=25
331
+
332
+ fast fund fastusd --to fast1someoneelse --amount 10
333
+ # → https://app.fast.xyz/send?to=fast1someoneelse&amount=10
334
+ ```
335
+
336
+ **Options:**
337
+
338
+ - `--to <fast1...>` — Recipient Fast address (default: active account).
339
+ - `--amount <decimal>` — Optional amount; if omitted, the web app prompts.
340
+
341
+ **Requirements:**
342
+
343
+ - Mainnet only.
344
+
345
+ ---
346
+
347
+ ### `fast authorize request`
348
+
349
+ Generate a one-time HPKE authorization request. The command creates a URL for the wallet user to open, and stores a short-lived key in `~/.fast/handover-pending.json` (mode 0600, up to 5 minutes).
350
+
351
+ ```bash
352
+ fast authorize request [--requester NAME] [--url URL]
353
+ ```
354
+
355
+ **Options:**
356
+
357
+ - `--requester <name>` — Optional label shown to the wallet user to identify who is requesting
358
+ - `--url <url>` — Override the wallet base URL the auth link points to (default: `https://app.fast.xyz/authorize`). Useful for local dev against a non-production wallet, e.g. `--url http://localhost:3000/authorize`.
359
+
360
+ **Output (human):**
361
+
362
+ ```
363
+ Authorization URL:
364
+ https://app.fast.xyz/authorize?data=eyJ...
365
+
366
+ Fingerprint: 123456
367
+ Expires at: 2026-05-25T12:05:00Z
368
+
369
+ Show the URL to the wallet user. Once they paste back the handover
370
+ code, run:
371
+ fast authorize complete --message '<paste here>'
372
+ ```
373
+
374
+ **Output (`--json`):**
375
+
376
+ ```json
377
+ {
378
+ "auth_url": "...",
379
+ "request_fingerprint": "123456",
380
+ "request_expires_at": "2026-05-25T12:05:00Z"
381
+ }
382
+ ```
383
+
384
+ **Security note:** `~/.fast/handover-pending.json` contains the HPKE one-time private key — not the account seed. An attacker who steals only this file cannot derive the account key; they would also need to intercept the handover code the wallet user pastes back. The file expires within 5 minutes and is deleted after a successful `authorize complete`.
385
+
386
+ ---
387
+
388
+ ### `fast authorize complete`
389
+
390
+ Decrypt a handover code returned by the wallet user and print the account private key to stdout.
391
+
392
+ ```bash
393
+ fast authorize complete [--message TEXT | --stdin] [--print-account] [--json]
394
+ ```
271
395
 
272
396
  **Options:**
273
- - `--chain <chain>` — Source EVM chain (required)
274
- - `--token <token>` — Token symbol or token ID (defaults to `USDC` / `testUSDC`)
275
- - `--eip-7702` — Use the smart deposit flow when supported
397
+
398
+ - `--message <text>` — Handover code or chat message containing it (bare base64url or quoted)
399
+ - `--stdin` — Read the handover code from stdin (e.g., `cat code.txt | fast authorize complete --stdin`)
400
+ - `--print-account` — Also print the derived Fast address and public key
401
+ - `--json` — Emit JSON output
402
+
403
+ If neither `--message` nor `--stdin` is provided, the CLI prompts interactively. With `--non-interactive`, absence of both flags is an error.
404
+
405
+ **Output (human, default):**
406
+
407
+ ```
408
+ 0x1313131313131313131313131313131313131313131313131313131313131313
409
+ ```
410
+
411
+ **Output (human, `--print-account`):**
412
+
413
+ ```
414
+ Private key: 0x1313...
415
+ Address: fast1abc...xyz
416
+ Public key: 0xdead...beef
417
+ ```
418
+
419
+ **Output (`--json`):**
420
+
421
+ ```json
422
+ { "private_key": "0x1313..." }
423
+ ```
424
+
425
+ After a successful decryption, `~/.fast/handover-pending.json` is deleted. On decryption failures, the state file is updated (or deleted after 3 attempts) so the same request may be retried.
276
426
 
277
427
  ---
278
428
 
@@ -285,9 +435,11 @@ fast pay https://api.example.com/premium
285
435
  ```
286
436
 
287
437
  **Positional arguments:**
438
+
288
439
  - `<url>` — URL of the x402-protected resource (required)
289
440
 
290
441
  **Options:**
442
+
291
443
  - `--dry-run` — Show payment details without actually paying
292
444
  - `--method <GET|POST|...>` — HTTP method (default: GET)
293
445
  - `--header <key:value>` — Custom request header (can be repeated)
@@ -324,12 +476,15 @@ fast network add my-custom-net --config ./network-config.json
324
476
  ```
325
477
 
326
478
  **Positional arguments:**
479
+
327
480
  - `<name>` — Unique name for the network
328
481
 
329
482
  **Options:**
483
+
330
484
  - `--config <path>` — Path to a JSON file with the network configuration (required)
331
485
 
332
486
  **Example JSON config (`network-config.json`):**
487
+
333
488
  ```json
334
489
  {
335
490
  "url": "https://api.fast.xyz/proxy-rest",
@@ -383,8 +538,11 @@ The CLI stores data in `~/.fast/`:
383
538
  # 1. Create an account
384
539
  fast account create --name my-account
385
540
 
386
- # 2. Get a fiat on-ramp URL
387
- fast fund fiat --network mainnet --address fast1...
541
+ # 2. Get a fiat on-ramp URL (delivers USDC to your Fast account)
542
+ fast fund usdc fiat --network mainnet --address fast1...
543
+
544
+ # 2b. Or open the unified Fast web app to fund fastUSD
545
+ fast fund fastusd --network mainnet
388
546
 
389
547
  # 3. Check your balance
390
548
  fast info balance --account my-account
@@ -7,7 +7,7 @@ import {
7
7
  getBundledNetworks,
8
8
  getVersion,
9
9
  isBundledNetwork
10
- } from "./chunk-ECO24H3M.js";
10
+ } from "./chunk-FLVU732R.js";
11
11
  import "./chunk-77HVPD4G.js";
12
12
  export {
13
13
  AppConfig,
@@ -1,20 +1,96 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  // src/services/config/app.ts
4
- import { Context, Layer, Schema as Schema2 } from "effect";
4
+ import { Context, Layer } from "effect";
5
5
 
6
- // src/config/app.json
7
- var app_default = {
8
- name: "fast",
9
- version: "1.0.1"
6
+ // package.json
7
+ var package_default = {
8
+ name: "@fastxyz/cli",
9
+ description: "Fast CLI - Account, network, and transaction management",
10
+ version: "1.1.0",
11
+ repository: {
12
+ type: "git",
13
+ url: "https://github.com/fastxyz/fast-sdk",
14
+ directory: "app/cli"
15
+ },
16
+ bin: {
17
+ fast: "./dist/main.js"
18
+ },
19
+ type: "module",
20
+ files: [
21
+ "dist",
22
+ "drizzle",
23
+ "README.md"
24
+ ],
25
+ scripts: {
26
+ build: "tsup",
27
+ prepack: "tsup",
28
+ dev: "tsup --watch",
29
+ test: "vitest run"
30
+ },
31
+ dependencies: {
32
+ "@clack/core": "^1.2.0",
33
+ "@effect/platform": "^0.96.0",
34
+ "@effect/platform-node": "^0.106.0",
35
+ "@effect/printer": "^0.49.0",
36
+ "@effect/printer-ansi": "^0.49.0",
37
+ "@effect/typeclass": "^0.40.0",
38
+ "@optique/core": "^0.10.7",
39
+ bech32: "^2.0.0",
40
+ "better-sqlite3": "^12.8.0",
41
+ "cli-table3": "^0.6.5",
42
+ "drizzle-orm": "^0.45.2",
43
+ effect: "^3.21.0",
44
+ uuid: "^11.1.0"
45
+ },
46
+ devDependencies: {
47
+ "@fastxyz/allset-sdk": "workspace:*",
48
+ "@fastxyz/schema": "workspace:*",
49
+ "@fastxyz/sdk": "workspace:*",
50
+ "@fastxyz/x402-client": "workspace:*",
51
+ "@noble/ciphers": "^1.3.0",
52
+ "@noble/curves": "^2.0.1",
53
+ "@noble/hashes": "^2.0.1",
54
+ "@types/better-sqlite3": "^7.6.13",
55
+ "@types/node": "^25.5.0",
56
+ "@types/uuid": "^10.0.0",
57
+ "drizzle-kit": "^0.31.10"
58
+ },
59
+ publishConfig: {
60
+ access: "public",
61
+ provenance: true
62
+ }
10
63
  };
11
64
 
12
- // src/config/networks.json
13
- var networks_default = {
65
+ // ../../packages/fast-sdk/dist/networks/index.js
66
+ var mainnet = {
67
+ url: "https://api.fast.xyz/proxy-rest",
68
+ explorerUrl: "https://explorer.fast.xyz",
69
+ networkId: "fast:mainnet",
70
+ defaultToken: {
71
+ tokenId: "0x125b60bb2e805336f0934077d4f9fdb36f45bec9ded8d7b0e637516cc43a86eb",
72
+ symbol: "fastUSD",
73
+ decimals: 6
74
+ }
75
+ };
76
+ var testnet = {
77
+ url: "https://testnet.api.fast.xyz/proxy-rest",
78
+ explorerUrl: "https://testnet.explorer.fast.xyz",
79
+ networkId: "fast:testnet",
80
+ defaultToken: {
81
+ tokenId: "0xd73a0679a2be46981e2a8aedecd951c8b6690e7d5f8502b34ed3ff4cc2163b46",
82
+ symbol: "testUSDC",
83
+ decimals: 6
84
+ }
85
+ };
86
+
87
+ // src/config/networks.ts
88
+ var bundledNetworks = {
14
89
  testnet: {
15
- url: "https://testnet.api.fast.xyz/proxy-rest",
16
- explorerUrl: "https://testnet.explorer.fast.xyz",
17
- networkId: "fast:testnet",
90
+ url: testnet.url,
91
+ explorerUrl: testnet.explorerUrl,
92
+ networkId: testnet.networkId,
93
+ defaultToken: testnet.defaultToken,
18
94
  allSet: {
19
95
  crossSignUrl: "https://testnet.cross-sign.allset.fast.xyz",
20
96
  portalApiUrl: "https://testnet.allset.fast.xyz/api",
@@ -53,9 +129,10 @@ var networks_default = {
53
129
  }
54
130
  },
55
131
  mainnet: {
56
- url: "https://api.fast.xyz/proxy-rest",
57
- explorerUrl: "https://explorer.fast.xyz",
58
- networkId: "fast:mainnet",
132
+ url: mainnet.url,
133
+ explorerUrl: mainnet.explorerUrl,
134
+ networkId: mainnet.networkId,
135
+ defaultToken: mainnet.defaultToken,
59
136
  allSet: {
60
137
  crossSignUrl: "https://cross-sign.allset.fast.xyz",
61
138
  portalApiUrl: "https://allset.fast.xyz/api",
@@ -110,44 +187,10 @@ var networks_default = {
110
187
  }
111
188
  };
112
189
 
113
- // src/schemas/networks.ts
114
- import { Schema } from "effect";
115
- var AllSetChainTokenSchema = Schema.Struct({
116
- evmAddress: Schema.String,
117
- fastTokenId: Schema.String,
118
- decimals: Schema.Number
119
- });
120
- var AllSetChainSchema = Schema.Struct({
121
- chainId: Schema.Number,
122
- bridgeContract: Schema.String,
123
- fastBridgeAddress: Schema.String,
124
- relayerUrl: Schema.String,
125
- evmRpcUrl: Schema.String,
126
- evmExplorerUrl: Schema.String,
127
- tokens: Schema.Record({ key: Schema.String, value: AllSetChainTokenSchema })
128
- });
129
- var AllSetConfigSchema = Schema.Struct({
130
- crossSignUrl: Schema.String,
131
- portalApiUrl: Schema.String,
132
- chains: Schema.Record({ key: Schema.String, value: AllSetChainSchema })
133
- });
134
- var NetworkConfigSchema = Schema.Struct({
135
- url: Schema.String,
136
- explorerUrl: Schema.String,
137
- networkId: Schema.String,
138
- allSet: Schema.optional(AllSetConfigSchema)
139
- });
140
- var BundledNetworksSchema = Schema.Record({
141
- key: Schema.String,
142
- value: NetworkConfigSchema
143
- });
144
-
145
190
  // src/services/config/app.ts
146
- var bundledNetworks = Schema2.decodeUnknownSync(
147
- BundledNetworksSchema
148
- )(networks_default);
149
- var getAppName = () => app_default.name;
150
- var getVersion = () => app_default.version;
191
+ var appName = Object.keys(package_default.bin)[0] ?? "fast";
192
+ var getAppName = () => appName;
193
+ var getVersion = () => package_default.version;
151
194
  var getBundledNetworks = () => bundledNetworks;
152
195
  var isBundledNetwork = (name) => Object.hasOwn(bundledNetworks, name);
153
196
  var getBundledNetwork = (name) => bundledNetworks[name];
@@ -162,7 +205,6 @@ var AppConfigLive = Layer.sync(AppConfig, () => ({
162
205
  }));
163
206
 
164
207
  export {
165
- NetworkConfigSchema,
166
208
  getAppName,
167
209
  getVersion,
168
210
  getBundledNetworks,