@1sat/cli 0.0.106 → 0.0.109
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 +17 -0
- package/dist/cli.js +111 -26
- package/package.json +4 -4
- package/src/commands/authfetch-request.ts +134 -0
- package/src/commands/authfetch.ts +25 -35
- package/src/help.ts +1 -1
package/README.md
CHANGED
|
@@ -331,3 +331,20 @@ The CLI is pure Bun with no framework. Arg parsing is manual (`src/args.ts`). Bu
|
|
|
331
331
|
## License
|
|
332
332
|
|
|
333
333
|
MIT
|
|
334
|
+
|
|
335
|
+
### Authenticated HTTP requests
|
|
336
|
+
|
|
337
|
+
`1sat authfetch <method> <url> [--body <json|@file>] [--header 'K: V']`
|
|
338
|
+
uses the SDK's BRC-104 AuthFetch with CLI wallet keys. If the SDK reports
|
|
339
|
+
missing response authentication headers, only GET and HEAD may retry using
|
|
340
|
+
plain fetch for public reads. Other methods fail with an unknown-outcome
|
|
341
|
+
warning: verify activity before retrying, since the server may already have
|
|
342
|
+
executed the request.
|
|
343
|
+
|
|
344
|
+
A 402 response requires interactive payment confirmation or explicit `--yes`.
|
|
345
|
+
Without `--yes` and a terminal on both stdin and stdout, the command returns
|
|
346
|
+
`approval_required` with exit status 1 and makes no payment retry. Use `--json`
|
|
347
|
+
for structured output; `satoshis` is included only when the public payment
|
|
348
|
+
header is a nonnegative safe integer of at most 16 decimal digits. Review the
|
|
349
|
+
payment before rerunning with `--yes`; this authorizes the existing SDK payment
|
|
350
|
+
flow. It does not impose a spending cap. `--quiet` suppresses output as usual.
|
package/dist/cli.js
CHANGED
|
@@ -1378,7 +1378,7 @@ var init_help = __esm(() => {
|
|
|
1378
1378
|
{
|
|
1379
1379
|
group: "Advanced",
|
|
1380
1380
|
name: "authfetch",
|
|
1381
|
-
description: "HTTP request with BRC-104 AuthFetch using CLI wallet keys. On 402,
|
|
1381
|
+
description: "HTTP request with BRC-104 AuthFetch using CLI wallet keys. Only GET/HEAD retry public routes without auth. On 402, requires --yes or interactive confirmation; noninteractive calls return approval_required and exit nonzero.",
|
|
1382
1382
|
positional: "<method> <url>",
|
|
1383
1383
|
args: [
|
|
1384
1384
|
{
|
|
@@ -1423,9 +1423,101 @@ var init_help = __esm(() => {
|
|
|
1423
1423
|
];
|
|
1424
1424
|
});
|
|
1425
1425
|
|
|
1426
|
+
// src/commands/authfetch-request.ts
|
|
1427
|
+
import { AuthFetch } from "@bsv/sdk";
|
|
1428
|
+
function createApprovalAuth(wallet) {
|
|
1429
|
+
let approved = false;
|
|
1430
|
+
let submitted = false;
|
|
1431
|
+
const guarded = new Proxy(wallet, {
|
|
1432
|
+
get(target, property) {
|
|
1433
|
+
if (property === "createAction")
|
|
1434
|
+
return async (...args) => {
|
|
1435
|
+
const satoshis = args[0].outputs?.reduce((sum, output2) => sum + output2.satoshis, 0) ?? 0;
|
|
1436
|
+
if (!Number.isSafeInteger(satoshis) || satoshis <= 0)
|
|
1437
|
+
throw new Error("Invalid HTTP payment amount");
|
|
1438
|
+
if (approved === false)
|
|
1439
|
+
throw new PaymentRequired(satoshis);
|
|
1440
|
+
if (typeof approved === "number" && satoshis !== approved)
|
|
1441
|
+
throw new Error("Payment amount changed; review the new quote before retrying");
|
|
1442
|
+
if (submitted)
|
|
1443
|
+
throw new Error("Payment already submitted; reconcile wallet activity before retrying");
|
|
1444
|
+
submitted = true;
|
|
1445
|
+
return target.createAction(...args);
|
|
1446
|
+
};
|
|
1447
|
+
if (property === "signAction")
|
|
1448
|
+
return async () => {
|
|
1449
|
+
throw new Error("Unexpected HTTP payment signing request");
|
|
1450
|
+
};
|
|
1451
|
+
const value = Reflect.get(target, property, target);
|
|
1452
|
+
return typeof value === "function" ? value.bind(target) : value;
|
|
1453
|
+
}
|
|
1454
|
+
});
|
|
1455
|
+
return {
|
|
1456
|
+
auth: new AuthFetch(guarded),
|
|
1457
|
+
authorizePayment: (satoshis) => {
|
|
1458
|
+
approved = satoshis ?? true;
|
|
1459
|
+
}
|
|
1460
|
+
};
|
|
1461
|
+
}
|
|
1462
|
+
async function requestWithApproval(url, init, options, dependencies) {
|
|
1463
|
+
let res;
|
|
1464
|
+
try {
|
|
1465
|
+
res = await dependencies.auth.fetch(url, {
|
|
1466
|
+
...init,
|
|
1467
|
+
paymentRetryAttempts: 1
|
|
1468
|
+
});
|
|
1469
|
+
} catch (error) {
|
|
1470
|
+
if (error instanceof PaymentRequired) {
|
|
1471
|
+
res = new Response(null, {
|
|
1472
|
+
status: 402,
|
|
1473
|
+
headers: { "x-bsv-payment-satoshis-required": String(error.satoshis) }
|
|
1474
|
+
});
|
|
1475
|
+
} else {
|
|
1476
|
+
const missingAuthentication = error instanceof Error && /^Received HTTP \d{3}(?: [^\n]*)? from /.test(error.message) && (error.message.includes(` from ${url} without valid BSV authentication (missing headers: `) || error.message.includes(` from ${url} without valid BSV authentication (response lacked required BSV auth headers)`));
|
|
1477
|
+
if (!missingAuthentication)
|
|
1478
|
+
throw error;
|
|
1479
|
+
if (init.method !== "GET" && init.method !== "HEAD") {
|
|
1480
|
+
throw new Error("Authentication could not be verified. The request outcome may be unknown; verify activity before retrying.", { cause: error });
|
|
1481
|
+
}
|
|
1482
|
+
res = await dependencies.plainFetch(url, init);
|
|
1483
|
+
}
|
|
1484
|
+
}
|
|
1485
|
+
if (res.status !== 402)
|
|
1486
|
+
return res;
|
|
1487
|
+
const amount = res.headers.get("x-bsv-payment-satoshis-required");
|
|
1488
|
+
const value = amount !== null && /^\d{1,16}$/.test(amount) ? Number(amount) : Number.NaN;
|
|
1489
|
+
const satoshis = Number.isSafeInteger(value) ? value : undefined;
|
|
1490
|
+
const message = satoshis !== undefined ? `Pay ${satoshis} sats for ${init.method} ${url}?` : `Server requires payment (402) for ${init.method} ${url}. Continue?`;
|
|
1491
|
+
if (!options.yes) {
|
|
1492
|
+
if (!options.interactive) {
|
|
1493
|
+
return {
|
|
1494
|
+
error: "approval_required",
|
|
1495
|
+
status: 402,
|
|
1496
|
+
ok: false,
|
|
1497
|
+
message: "Payment requires approval. Review the payment and rerun with --yes to authorize it, or run in an interactive terminal.",
|
|
1498
|
+
...satoshis !== undefined ? { satoshis } : {}
|
|
1499
|
+
};
|
|
1500
|
+
}
|
|
1501
|
+
if (!await dependencies.confirmPayment(message)) {
|
|
1502
|
+
throw new Error("Payment cancelled.");
|
|
1503
|
+
}
|
|
1504
|
+
}
|
|
1505
|
+
dependencies.authorizePayment?.(satoshis);
|
|
1506
|
+
return dependencies.auth.fetch(url, { ...init, paymentRetryAttempts: 1 });
|
|
1507
|
+
}
|
|
1508
|
+
var PaymentRequired;
|
|
1509
|
+
var init_authfetch_request = __esm(() => {
|
|
1510
|
+
PaymentRequired = class PaymentRequired extends Error {
|
|
1511
|
+
satoshis;
|
|
1512
|
+
constructor(satoshis) {
|
|
1513
|
+
super("Payment requires approval");
|
|
1514
|
+
this.satoshis = satoshis;
|
|
1515
|
+
}
|
|
1516
|
+
};
|
|
1517
|
+
});
|
|
1518
|
+
|
|
1426
1519
|
// src/commands/authfetch.ts
|
|
1427
1520
|
import { readFileSync as readFileSync5 } from "node:fs";
|
|
1428
|
-
import { AuthFetch } from "@bsv/sdk";
|
|
1429
1521
|
import { confirm, isCancel as isCancel2 } from "@clack/prompts";
|
|
1430
1522
|
async function handleAuthfetchCommand(args, opts) {
|
|
1431
1523
|
if (!args[0] || args[0] === "help" || args.includes("--help") || args.includes("-h")) {
|
|
@@ -1494,36 +1586,28 @@ Unknown or missing method: ${method ?? ""}`);
|
|
|
1494
1586
|
chain: opts.chain
|
|
1495
1587
|
});
|
|
1496
1588
|
try {
|
|
1497
|
-
const auth =
|
|
1589
|
+
const { auth, authorizePayment } = createApprovalAuth(walletResult.wallet);
|
|
1498
1590
|
const init = {
|
|
1499
1591
|
method,
|
|
1500
1592
|
headers,
|
|
1501
1593
|
...body !== undefined ? { body } : {}
|
|
1502
1594
|
};
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
|
|
1511
|
-
|
|
1512
|
-
|
|
1513
|
-
} else {
|
|
1514
|
-
throw err;
|
|
1515
|
-
}
|
|
1516
|
-
}
|
|
1517
|
-
if (res.status === 402) {
|
|
1518
|
-
const satsHeader = res.headers.get("x-bsv-payment-satoshis-required");
|
|
1519
|
-
const sats = satsHeader ? Number(satsHeader) : undefined;
|
|
1520
|
-
const payMsg = sats != null && Number.isFinite(sats) ? `Pay ${sats} sats for ${method} ${url}?` : `Server requires payment (402) for ${method} ${url}. Continue?`;
|
|
1521
|
-
if (!opts.yes) {
|
|
1522
|
-
const ok = await confirm({ message: payMsg });
|
|
1523
|
-
if (isCancel2(ok) || !ok)
|
|
1524
|
-
fatal("Payment cancelled.");
|
|
1595
|
+
const res = await requestWithApproval(url, init, {
|
|
1596
|
+
yes: opts.yes,
|
|
1597
|
+
interactive: Boolean(process.stdin.isTTY && process.stdout.isTTY)
|
|
1598
|
+
}, {
|
|
1599
|
+
auth,
|
|
1600
|
+
authorizePayment,
|
|
1601
|
+
plainFetch: fetch,
|
|
1602
|
+
confirmPayment: async (message) => {
|
|
1603
|
+
const ok = await confirm({ message });
|
|
1604
|
+
return !isCancel2(ok) && ok === true;
|
|
1525
1605
|
}
|
|
1526
|
-
|
|
1606
|
+
});
|
|
1607
|
+
if ("error" in res) {
|
|
1608
|
+
output(res, opts);
|
|
1609
|
+
process.exitCode = 1;
|
|
1610
|
+
return;
|
|
1527
1611
|
}
|
|
1528
1612
|
const text = await res.text();
|
|
1529
1613
|
let parsed = text;
|
|
@@ -1562,6 +1646,7 @@ var init_authfetch = __esm(() => {
|
|
|
1562
1646
|
init_help();
|
|
1563
1647
|
init_keys();
|
|
1564
1648
|
init_output();
|
|
1649
|
+
init_authfetch_request();
|
|
1565
1650
|
METHODS = new Set([
|
|
1566
1651
|
"GET",
|
|
1567
1652
|
"POST",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@1sat/cli",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.109",
|
|
4
4
|
"description": "CLI for 1Sat Ordinals SDK",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/cli.js",
|
|
@@ -27,11 +27,11 @@
|
|
|
27
27
|
],
|
|
28
28
|
"license": "MIT",
|
|
29
29
|
"dependencies": {
|
|
30
|
-
"@1sat/actions": "0.0.
|
|
30
|
+
"@1sat/actions": "0.0.207",
|
|
31
31
|
"@1sat/client": "0.0.51",
|
|
32
32
|
"@1sat/types": "0.0.41",
|
|
33
|
-
"@1sat/wallet-node": "0.0.
|
|
34
|
-
"@1sat/wallet-server": "0.0.
|
|
33
|
+
"@1sat/wallet-node": "0.0.73",
|
|
34
|
+
"@1sat/wallet-server": "0.0.48",
|
|
35
35
|
"@bsv/sdk": "^2.1.9",
|
|
36
36
|
"@bsv/wallet-toolbox": "npm:@bopen-io/wallet-toolbox@2.6.2-brc153.5",
|
|
37
37
|
"chalk": "^5.0.0",
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
import { AuthFetch, type WalletInterface } from '@bsv/sdk'
|
|
2
|
+
|
|
3
|
+
class PaymentRequired extends Error {
|
|
4
|
+
constructor(readonly satoshis: number) {
|
|
5
|
+
super('Payment requires approval')
|
|
6
|
+
}
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
/** Enforce approval at the wallet boundary; SDK retry=0 does not disable payment. */
|
|
10
|
+
export function createApprovalAuth(wallet: WalletInterface) {
|
|
11
|
+
let approved: false | number | true = false
|
|
12
|
+
let submitted = false
|
|
13
|
+
const guarded = new Proxy(wallet, {
|
|
14
|
+
get(target, property) {
|
|
15
|
+
if (property === 'createAction')
|
|
16
|
+
return async (...args: Parameters<WalletInterface['createAction']>) => {
|
|
17
|
+
const satoshis =
|
|
18
|
+
args[0].outputs?.reduce(
|
|
19
|
+
(sum, output) => sum + output.satoshis,
|
|
20
|
+
0,
|
|
21
|
+
) ?? 0
|
|
22
|
+
if (!Number.isSafeInteger(satoshis) || satoshis <= 0)
|
|
23
|
+
throw new Error('Invalid HTTP payment amount')
|
|
24
|
+
if (approved === false) throw new PaymentRequired(satoshis)
|
|
25
|
+
if (typeof approved === 'number' && satoshis !== approved)
|
|
26
|
+
throw new Error(
|
|
27
|
+
'Payment amount changed; review the new quote before retrying',
|
|
28
|
+
)
|
|
29
|
+
if (submitted)
|
|
30
|
+
throw new Error(
|
|
31
|
+
'Payment already submitted; reconcile wallet activity before retrying',
|
|
32
|
+
)
|
|
33
|
+
submitted = true
|
|
34
|
+
return target.createAction(...args)
|
|
35
|
+
}
|
|
36
|
+
if (property === 'signAction')
|
|
37
|
+
return async () => {
|
|
38
|
+
throw new Error('Unexpected HTTP payment signing request')
|
|
39
|
+
}
|
|
40
|
+
const value = Reflect.get(target, property, target)
|
|
41
|
+
return typeof value === 'function' ? value.bind(target) : value
|
|
42
|
+
},
|
|
43
|
+
})
|
|
44
|
+
return {
|
|
45
|
+
auth: new AuthFetch(guarded),
|
|
46
|
+
authorizePayment: (satoshis?: number) => {
|
|
47
|
+
approved = satoshis ?? true
|
|
48
|
+
},
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export interface PaymentApprovalRequired {
|
|
53
|
+
error: 'approval_required'
|
|
54
|
+
status: 402
|
|
55
|
+
ok: false
|
|
56
|
+
message: string
|
|
57
|
+
satoshis?: number
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/** Keep request replay and payment decisions separate from wallet setup/output. */
|
|
61
|
+
export async function requestWithApproval(
|
|
62
|
+
url: string,
|
|
63
|
+
init: RequestInit & { method: string },
|
|
64
|
+
options: { yes?: boolean; interactive: boolean },
|
|
65
|
+
dependencies: {
|
|
66
|
+
auth: Pick<AuthFetch, 'fetch'>
|
|
67
|
+
plainFetch: typeof fetch
|
|
68
|
+
confirmPayment: (message: string) => Promise<boolean>
|
|
69
|
+
authorizePayment?: (satoshis?: number) => void
|
|
70
|
+
},
|
|
71
|
+
): Promise<Response | PaymentApprovalRequired> {
|
|
72
|
+
let res: Response
|
|
73
|
+
try {
|
|
74
|
+
res = await dependencies.auth.fetch(url, {
|
|
75
|
+
...init,
|
|
76
|
+
paymentRetryAttempts: 1,
|
|
77
|
+
})
|
|
78
|
+
} catch (error) {
|
|
79
|
+
if (error instanceof PaymentRequired) {
|
|
80
|
+
res = new Response(null, {
|
|
81
|
+
status: 402,
|
|
82
|
+
headers: { 'x-bsv-payment-satoshis-required': String(error.satoshis) },
|
|
83
|
+
})
|
|
84
|
+
} else {
|
|
85
|
+
// Match only the SDK's known unauthenticated-response error, not
|
|
86
|
+
// transport, signature verification, or other authentication failures.
|
|
87
|
+
const missingAuthentication =
|
|
88
|
+
error instanceof Error &&
|
|
89
|
+
/^Received HTTP \d{3}(?: [^\n]*)? from /.test(error.message) &&
|
|
90
|
+
(error.message.includes(
|
|
91
|
+
` from ${url} without valid BSV authentication (missing headers: `,
|
|
92
|
+
) ||
|
|
93
|
+
error.message.includes(
|
|
94
|
+
` from ${url} without valid BSV authentication (response lacked required BSV auth headers)`,
|
|
95
|
+
))
|
|
96
|
+
if (!missingAuthentication) throw error
|
|
97
|
+
if (init.method !== 'GET' && init.method !== 'HEAD') {
|
|
98
|
+
throw new Error(
|
|
99
|
+
'Authentication could not be verified. The request outcome may be unknown; verify activity before retrying.',
|
|
100
|
+
{ cause: error },
|
|
101
|
+
)
|
|
102
|
+
}
|
|
103
|
+
res = await dependencies.plainFetch(url, init)
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
if (res.status !== 402) return res
|
|
108
|
+
|
|
109
|
+
const amount = res.headers.get('x-bsv-payment-satoshis-required')
|
|
110
|
+
const value =
|
|
111
|
+
amount !== null && /^\d{1,16}$/.test(amount) ? Number(amount) : Number.NaN
|
|
112
|
+
const satoshis = Number.isSafeInteger(value) ? value : undefined
|
|
113
|
+
const message =
|
|
114
|
+
satoshis !== undefined
|
|
115
|
+
? `Pay ${satoshis} sats for ${init.method} ${url}?`
|
|
116
|
+
: `Server requires payment (402) for ${init.method} ${url}. Continue?`
|
|
117
|
+
if (!options.yes) {
|
|
118
|
+
if (!options.interactive) {
|
|
119
|
+
return {
|
|
120
|
+
error: 'approval_required',
|
|
121
|
+
status: 402,
|
|
122
|
+
ok: false,
|
|
123
|
+
message:
|
|
124
|
+
'Payment requires approval. Review the payment and rerun with --yes to authorize it, or run in an interactive terminal.',
|
|
125
|
+
...(satoshis !== undefined ? { satoshis } : {}),
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
if (!(await dependencies.confirmPayment(message))) {
|
|
129
|
+
throw new Error('Payment cancelled.')
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
dependencies.authorizePayment?.(satoshis)
|
|
133
|
+
return dependencies.auth.fetch(url, { ...init, paymentRetryAttempts: 1 })
|
|
134
|
+
}
|
|
@@ -3,18 +3,18 @@
|
|
|
3
3
|
*
|
|
4
4
|
* 1sat authfetch <method> <url> [--body <json|@file>] [--header 'K: V']...
|
|
5
5
|
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
6
|
+
* Authenticates first; only GET/HEAD may retry public routes without auth.
|
|
7
|
+
* Payment requires --yes or interactive confirmation.
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
import { readFileSync } from 'node:fs'
|
|
11
|
-
import { AuthFetch } from '@bsv/sdk'
|
|
12
11
|
import { confirm, isCancel } from '@clack/prompts'
|
|
13
12
|
import type { GlobalFlags } from '../args.js'
|
|
14
13
|
import { loadContext } from '../context.js'
|
|
15
14
|
import { printCommandHelp } from '../help.js'
|
|
16
15
|
import { loadKey } from '../keys.js'
|
|
17
16
|
import { fatal, output } from '../output.js'
|
|
17
|
+
import { createApprovalAuth, requestWithApproval } from './authfetch-request.js'
|
|
18
18
|
|
|
19
19
|
const METHODS = new Set([
|
|
20
20
|
'GET',
|
|
@@ -107,44 +107,34 @@ export async function handleAuthfetchCommand(
|
|
|
107
107
|
})
|
|
108
108
|
|
|
109
109
|
try {
|
|
110
|
-
const auth =
|
|
110
|
+
const { auth, authorizePayment } = createApprovalAuth(walletResult.wallet)
|
|
111
111
|
const init = {
|
|
112
112
|
method,
|
|
113
113
|
headers,
|
|
114
114
|
...(body !== undefined ? { body } : {}),
|
|
115
115
|
}
|
|
116
116
|
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
if (
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
sats != null && Number.isFinite(sats)
|
|
139
|
-
? `Pay ${sats} sats for ${method} ${url}?`
|
|
140
|
-
: `Server requires payment (402) for ${method} ${url}. Continue?`
|
|
141
|
-
|
|
142
|
-
if (!opts.yes) {
|
|
143
|
-
const ok = await confirm({ message: payMsg })
|
|
144
|
-
if (isCancel(ok) || !ok) fatal('Payment cancelled.')
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
res = await auth.fetch(url, init)
|
|
117
|
+
const res = await requestWithApproval(
|
|
118
|
+
url,
|
|
119
|
+
init,
|
|
120
|
+
{
|
|
121
|
+
yes: opts.yes,
|
|
122
|
+
interactive: Boolean(process.stdin.isTTY && process.stdout.isTTY),
|
|
123
|
+
},
|
|
124
|
+
{
|
|
125
|
+
auth,
|
|
126
|
+
authorizePayment,
|
|
127
|
+
plainFetch: fetch,
|
|
128
|
+
confirmPayment: async (message) => {
|
|
129
|
+
const ok = await confirm({ message })
|
|
130
|
+
return !isCancel(ok) && ok === true
|
|
131
|
+
},
|
|
132
|
+
},
|
|
133
|
+
)
|
|
134
|
+
if ('error' in res) {
|
|
135
|
+
output(res, opts)
|
|
136
|
+
process.exitCode = 1
|
|
137
|
+
return
|
|
148
138
|
}
|
|
149
139
|
|
|
150
140
|
const text = await res.text()
|
package/src/help.ts
CHANGED
|
@@ -763,7 +763,7 @@ export const COMMANDS: CommandSpec[] = [
|
|
|
763
763
|
group: 'Advanced',
|
|
764
764
|
name: 'authfetch',
|
|
765
765
|
description:
|
|
766
|
-
'HTTP request with BRC-104 AuthFetch using CLI wallet keys. On 402,
|
|
766
|
+
'HTTP request with BRC-104 AuthFetch using CLI wallet keys. Only GET/HEAD retry public routes without auth. On 402, requires --yes or interactive confirmation; noninteractive calls return approval_required and exit nonzero.',
|
|
767
767
|
positional: '<method> <url>',
|
|
768
768
|
args: [
|
|
769
769
|
{
|