mppx 0.6.3 → 0.6.5
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/CHANGELOG.md +14 -0
- package/dist/Credential.d.ts +4 -0
- package/dist/Credential.d.ts.map +1 -1
- package/dist/Credential.js +18 -2
- package/dist/Credential.js.map +1 -1
- package/dist/bin.js +1 -1
- package/dist/bin.js.map +1 -1
- package/dist/cli/cli.d.ts.map +1 -1
- package/dist/cli/cli.js +166 -54
- package/dist/cli/cli.js.map +1 -1
- package/dist/discovery/Discovery.d.ts +234 -18
- package/dist/discovery/Discovery.d.ts.map +1 -1
- package/dist/discovery/Discovery.js +24 -2
- package/dist/discovery/Discovery.js.map +1 -1
- package/dist/discovery/OpenApi.d.ts +1 -1
- package/dist/discovery/OpenApi.d.ts.map +1 -1
- package/dist/discovery/OpenApi.js +2 -1
- package/dist/discovery/OpenApi.js.map +1 -1
- package/dist/discovery/Validate.d.ts.map +1 -1
- package/dist/discovery/Validate.js +2 -1
- package/dist/discovery/Validate.js.map +1 -1
- package/dist/stripe/server/internal/html.gen.d.ts +1 -1
- package/dist/stripe/server/internal/html.gen.d.ts.map +1 -1
- package/dist/stripe/server/internal/html.gen.js +1 -1
- package/dist/stripe/server/internal/html.gen.js.map +1 -1
- package/dist/tempo/client/Charge.js +1 -1
- package/dist/tempo/client/Charge.js.map +1 -1
- package/dist/tempo/internal/proof.d.ts +6 -2
- package/dist/tempo/internal/proof.d.ts.map +1 -1
- package/dist/tempo/internal/proof.js +7 -4
- package/dist/tempo/internal/proof.js.map +1 -1
- package/dist/tempo/server/Charge.d.ts.map +1 -1
- package/dist/tempo/server/Charge.js +4 -3
- package/dist/tempo/server/Charge.js.map +1 -1
- package/dist/tempo/server/internal/html.gen.d.ts +1 -1
- package/dist/tempo/server/internal/html.gen.d.ts.map +1 -1
- package/dist/tempo/server/internal/html.gen.js +1 -1
- package/dist/tempo/server/internal/html.gen.js.map +1 -1
- package/package.json +1 -1
- package/src/Challenge.test.ts +45 -0
- package/src/Credential.test.ts +66 -0
- package/src/Credential.ts +23 -3
- package/src/bin.ts +1 -1
- package/src/cli/cli.ts +194 -58
- package/src/cli/mcp.test.ts +233 -0
- package/src/discovery/Discovery.test.ts +66 -4
- package/src/discovery/Discovery.ts +40 -7
- package/src/discovery/OpenApi.test.ts +61 -33
- package/src/discovery/OpenApi.ts +2 -2
- package/src/discovery/Validate.test.ts +117 -0
- package/src/discovery/Validate.ts +2 -1
- package/src/middlewares/elysia.test.ts +1 -1
- package/src/middlewares/express.test.ts +1 -1
- package/src/middlewares/hono.test.ts +1 -1
- package/src/middlewares/nextjs.test.ts +1 -1
- package/src/proxy/Proxy.test.ts +3 -3
- package/src/stripe/server/internal/html.gen.ts +1 -1
- package/src/tempo/client/Charge.ts +1 -1
- package/src/tempo/internal/proof.test.ts +11 -5
- package/src/tempo/internal/proof.ts +7 -4
- package/src/tempo/server/Charge.test.ts +51 -15
- package/src/tempo/server/Charge.ts +5 -3
- package/src/tempo/server/internal/html.gen.ts +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
# mppx
|
|
2
2
|
|
|
3
|
+
## 0.6.5
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 3c5cd4b: Fixed zero-amount Tempo proof credentials to bind signatures to the challenge realm.
|
|
8
|
+
- 24604ff: Fixed MCP stdio startup and returned structured CLI command results without writing raw tool output to stdout.
|
|
9
|
+
|
|
10
|
+
## 0.6.4
|
|
11
|
+
|
|
12
|
+
### Patch Changes
|
|
13
|
+
|
|
14
|
+
- 0d1e548: Fixed credential `opaque` serialization to use the spec-compliant base64url string shape, while keeping deserialization backward-compatible with legacy object-shaped credentials.
|
|
15
|
+
- 9536014: Added canonical discovery output using `x-payment-info.offers[]` while continuing to accept the legacy flat shorthand during validation and parsing.
|
|
16
|
+
|
|
3
17
|
## 0.6.3
|
|
4
18
|
|
|
5
19
|
### Patch Changes
|
package/dist/Credential.d.ts
CHANGED
|
@@ -24,6 +24,8 @@ export declare class InvalidCredentialEncodingError extends Error {
|
|
|
24
24
|
}
|
|
25
25
|
/**
|
|
26
26
|
* Deserializes an Authorization header value to a credential.
|
|
27
|
+
* Accepts the spec-compliant base64url `opaque` string shape and the legacy
|
|
28
|
+
* object-shaped `opaque` form emitted by older mppx versions.
|
|
27
29
|
*
|
|
28
30
|
* @param header - The Authorization header value.
|
|
29
31
|
* @returns The deserialized credential.
|
|
@@ -79,6 +81,8 @@ export declare namespace from {
|
|
|
79
81
|
export declare function fromRequest<payload = unknown>(request: Request): Credential<payload>;
|
|
80
82
|
/**
|
|
81
83
|
* Serializes a credential to the Authorization header format.
|
|
84
|
+
* When present, `challenge.opaque` is encoded as the base64url string required
|
|
85
|
+
* by the Payment auth credential format.
|
|
82
86
|
*
|
|
83
87
|
* @param credential - The credential to serialize.
|
|
84
88
|
* @returns A string suitable for the Authorization header value.
|
package/dist/Credential.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Credential.d.ts","sourceRoot":"","sources":["../src/Credential.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,SAAS,MAAM,gBAAgB,CAAA;AAG3C;;GAEG;AACH,MAAM,MAAM,UAAU,CACpB,OAAO,GAAG,OAAO,EACjB,SAAS,SAAS,SAAS,CAAC,SAAS,GAAG,SAAS,CAAC,SAAS,IACzD;IACF,2CAA2C;IAC3C,SAAS,EAAE,SAAS,CAAA;IACpB,qCAAqC;IACrC,OAAO,EAAE,OAAO,CAAA;IAChB,2EAA2E;IAC3E,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB,CAAA;AAED,qBAAa,+BAAgC,SAAQ,KAAK;IACxD,SAAkB,IAAI,qCAAoC;;CAK3D;AAED,qBAAa,yBAA0B,SAAQ,KAAK;IAClD,SAAkB,IAAI,+BAA8B;;CAKrD;AAED,qBAAa,8BAA+B,SAAQ,KAAK;IACvD,SAAkB,IAAI,oCAAmC;;CAK1D;AAED
|
|
1
|
+
{"version":3,"file":"Credential.d.ts","sourceRoot":"","sources":["../src/Credential.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,SAAS,MAAM,gBAAgB,CAAA;AAG3C;;GAEG;AACH,MAAM,MAAM,UAAU,CACpB,OAAO,GAAG,OAAO,EACjB,SAAS,SAAS,SAAS,CAAC,SAAS,GAAG,SAAS,CAAC,SAAS,IACzD;IACF,2CAA2C;IAC3C,SAAS,EAAE,SAAS,CAAA;IACpB,qCAAqC;IACrC,OAAO,EAAE,OAAO,CAAA;IAChB,2EAA2E;IAC3E,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB,CAAA;AAED,qBAAa,+BAAgC,SAAQ,KAAK;IACxD,SAAkB,IAAI,qCAAoC;;CAK3D;AAED,qBAAa,yBAA0B,SAAQ,KAAK;IAClD,SAAkB,IAAI,+BAA8B;;CAKrD;AAED,qBAAa,8BAA+B,SAAQ,KAAK;IACvD,SAAkB,IAAI,oCAAmC;;CAK1D;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,WAAW,CAAC,OAAO,GAAG,OAAO,EAAE,KAAK,EAAE,MAAM,GAAG,UAAU,CAAC,OAAO,CAAC,CAoCjF;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,IAAI,CAAC,KAAK,CAAC,UAAU,SAAS,IAAI,CAAC,UAAU,EAC3D,UAAU,EAAE,UAAU,GACrB,UAAU,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,UAAU,CAAC,WAAW,CAAC,CAAC,CAO5D;AAED,MAAM,CAAC,OAAO,WAAW,IAAI,CAAC;IAC5B,KAAK,UAAU,GAAG;QAChB,2CAA2C;QAC3C,SAAS,EAAE,SAAS,CAAC,SAAS,CAAA;QAC9B,qCAAqC;QACrC,OAAO,EAAE,OAAO,CAAA;QAChB,2EAA2E;QAC3E,MAAM,CAAC,EAAE,MAAM,CAAA;KAChB,CAAA;CACF;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,WAAW,CAAC,OAAO,GAAG,OAAO,EAAE,OAAO,EAAE,OAAO,GAAG,UAAU,CAAC,OAAO,CAAC,CAMpF;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,SAAS,CAAC,UAAU,EAAE,UAAU,GAAG,MAAM,CAcxD;AAED;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAGlE"}
|
package/dist/Credential.js
CHANGED
|
@@ -21,6 +21,8 @@ export class InvalidCredentialEncodingError extends Error {
|
|
|
21
21
|
}
|
|
22
22
|
/**
|
|
23
23
|
* Deserializes an Authorization header value to a credential.
|
|
24
|
+
* Accepts the spec-compliant base64url `opaque` string shape and the legacy
|
|
25
|
+
* object-shaped `opaque` form emitted by older mppx versions.
|
|
24
26
|
*
|
|
25
27
|
* @param header - The Authorization header value.
|
|
26
28
|
* @returns The deserialized credential.
|
|
@@ -41,6 +43,16 @@ export function deserialize(value) {
|
|
|
41
43
|
const parsed = JSON.parse(json);
|
|
42
44
|
const challenge = Challenge.Schema.parse({
|
|
43
45
|
...parsed.challenge,
|
|
46
|
+
...(parsed.challenge.opaque !== undefined && {
|
|
47
|
+
// TODO: Drop the legacy object-shaped `opaque` fallback after old mppx
|
|
48
|
+
// clients are no longer in circulation. Older mppx versions echoed
|
|
49
|
+
// `opaque` as an expanded JSON object in credentials, but the Payment
|
|
50
|
+
// auth spec requires clients to return the original base64url string
|
|
51
|
+
// unchanged in the credential challenge object.
|
|
52
|
+
opaque: typeof parsed.challenge.opaque === 'string'
|
|
53
|
+
? PaymentRequest.deserialize(parsed.challenge.opaque)
|
|
54
|
+
: parsed.challenge.opaque,
|
|
55
|
+
}),
|
|
44
56
|
request: PaymentRequest.deserialize(parsed.challenge.request),
|
|
45
57
|
});
|
|
46
58
|
return {
|
|
@@ -101,6 +113,8 @@ export function fromRequest(request) {
|
|
|
101
113
|
}
|
|
102
114
|
/**
|
|
103
115
|
* Serializes a credential to the Authorization header format.
|
|
116
|
+
* When present, `challenge.opaque` is encoded as the base64url string required
|
|
117
|
+
* by the Payment auth credential format.
|
|
104
118
|
*
|
|
105
119
|
* @param credential - The credential to serialize.
|
|
106
120
|
* @returns A string suitable for the Authorization header value.
|
|
@@ -114,10 +128,12 @@ export function fromRequest(request) {
|
|
|
114
128
|
* ```
|
|
115
129
|
*/
|
|
116
130
|
export function serialize(credential) {
|
|
131
|
+
const { opaque, request, ...challenge } = credential.challenge;
|
|
117
132
|
const wire = {
|
|
118
133
|
challenge: {
|
|
119
|
-
...
|
|
120
|
-
|
|
134
|
+
...challenge,
|
|
135
|
+
...(opaque !== undefined && { opaque: PaymentRequest.serialize(opaque) }),
|
|
136
|
+
request: PaymentRequest.serialize(request),
|
|
121
137
|
},
|
|
122
138
|
payload: credential.payload,
|
|
123
139
|
...(credential.source && { source: credential.source }),
|
package/dist/Credential.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Credential.js","sourceRoot":"","sources":["../src/Credential.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,IAAI,CAAA;AAE3B,OAAO,KAAK,SAAS,MAAM,gBAAgB,CAAA;AAC3C,OAAO,KAAK,cAAc,MAAM,qBAAqB,CAAA;AAiBrD,MAAM,OAAO,+BAAgC,SAAQ,KAAK;IACtC,IAAI,GAAG,iCAAiC,CAAA;IAE1D;QACE,KAAK,CAAC,+BAA+B,CAAC,CAAA;IACxC,CAAC;CACF;AAED,MAAM,OAAO,yBAA0B,SAAQ,KAAK;IAChC,IAAI,GAAG,2BAA2B,CAAA;IAEpD;QACE,KAAK,CAAC,yBAAyB,CAAC,CAAA;IAClC,CAAC;CACF;AAED,MAAM,OAAO,8BAA+B,SAAQ,KAAK;IACrC,IAAI,GAAG,gCAAgC,CAAA;IAEzD;QACE,KAAK,CAAC,4BAA4B,CAAC,CAAA;IACrC,CAAC;CACF;AAED
|
|
1
|
+
{"version":3,"file":"Credential.js","sourceRoot":"","sources":["../src/Credential.ts"],"names":[],"mappings":"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"}
|
package/dist/bin.js
CHANGED
package/dist/bin.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bin.js","sourceRoot":"","sources":["../src/bin.ts"],"names":[],"mappings":";AACA,OAAO,GAAG,MAAM,cAAc,CAAA;AAE9B,GAAG,CAAC,KAAK,EAAE,
|
|
1
|
+
{"version":3,"file":"bin.js","sourceRoot":"","sources":["../src/bin.ts"],"names":[],"mappings":";AACA,OAAO,GAAG,MAAM,cAAc,CAAA;AAE9B,MAAM,GAAG,CAAC,KAAK,EAAE,CAAA"}
|
package/dist/cli/cli.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../../src/cli/cli.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,GAAG,EAAa,MAAM,OAAO,CAAA;
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../../src/cli/cli.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,GAAG,EAAa,MAAM,OAAO,CAAA;AA6EtC,QAAA,MAAM,GAAG;;;;;;;;;;;;;;;;;;;;;;;;wBAscP,CAAA;AA8uBF,eAAe,GAAG,CAAA"}
|
package/dist/cli/cli.js
CHANGED
|
@@ -15,6 +15,37 @@ import { loadConfig, resolveAcceptPayment, selectChallenge } from './internal.js
|
|
|
15
15
|
import { readTempoKeystore, resolveTempoAccount } from './plugins/tempo.js';
|
|
16
16
|
import { chainName, confirm, decodeMemo, fetchBalanceLines, fmtBalance, fmtChallengeValue, fmtRequestValue, isTempoAccount, link, parseMethodOpts, pc, printRequestHeaders, printResponseHeaders, prompt, resolveChain, resolveRpcUrl, } from './utils.js';
|
|
17
17
|
const packageJson = createRequire(import.meta.url)('../../package.json');
|
|
18
|
+
const accountSummarySchema = z.object({
|
|
19
|
+
address: z.string(),
|
|
20
|
+
isDefault: z.boolean().optional(),
|
|
21
|
+
name: z.string(),
|
|
22
|
+
source: z.string().optional(),
|
|
23
|
+
});
|
|
24
|
+
const accountViewSchema = z.object({
|
|
25
|
+
address: z.string(),
|
|
26
|
+
balances: z.array(z.string()).optional(),
|
|
27
|
+
name: z.string(),
|
|
28
|
+
type: z.string().optional(),
|
|
29
|
+
});
|
|
30
|
+
const discoveryIssueSchema = z.object({
|
|
31
|
+
message: z.string(),
|
|
32
|
+
path: z.string(),
|
|
33
|
+
severity: z.string(),
|
|
34
|
+
});
|
|
35
|
+
function shouldReturnStructured(c) {
|
|
36
|
+
return c.format === 'json' && c.formatExplicit;
|
|
37
|
+
}
|
|
38
|
+
function outputResult(c, data, print) {
|
|
39
|
+
if (shouldReturnStructured(c))
|
|
40
|
+
return c.ok(data);
|
|
41
|
+
print();
|
|
42
|
+
return undefined;
|
|
43
|
+
}
|
|
44
|
+
function canReadCommandStdin() {
|
|
45
|
+
if (process.stdin.isTTY !== false)
|
|
46
|
+
return false;
|
|
47
|
+
return process.stdin.listenerCount('data') === 0 && process.stdin.listenerCount('readable') === 0;
|
|
48
|
+
}
|
|
18
49
|
const cli = Cli.create('mppx', {
|
|
19
50
|
version: packageJson.version,
|
|
20
51
|
description: 'Make HTTP requests with automatic payment handling',
|
|
@@ -468,26 +499,40 @@ const account = Cli.create('account', {
|
|
|
468
499
|
account: z.string().optional().describe('Account name (env: MPPX_ACCOUNT)'),
|
|
469
500
|
rpcUrl: z.string().optional().describe('RPC endpoint (env: MPPX_RPC_URL)'),
|
|
470
501
|
}),
|
|
502
|
+
output: z.object({ address: z.string(), name: z.string() }),
|
|
471
503
|
alias: { account: 'a', rpcUrl: 'r' },
|
|
472
504
|
async run(c) {
|
|
505
|
+
const structured = shouldReturnStructured(c);
|
|
473
506
|
let resolvedName = c.options.account;
|
|
474
507
|
if (!resolvedName) {
|
|
475
508
|
const existing = await createKeychain().list();
|
|
476
509
|
if (existing.length === 0)
|
|
477
510
|
resolvedName = 'main';
|
|
478
511
|
else {
|
|
512
|
+
if (structured)
|
|
513
|
+
return c.error({
|
|
514
|
+
code: 'ACCOUNT_REQUIRED',
|
|
515
|
+
message: 'Account name is required in structured mode.',
|
|
516
|
+
exitCode: 2,
|
|
517
|
+
});
|
|
479
518
|
const input = await prompt('Account name');
|
|
480
519
|
if (!input)
|
|
481
|
-
return;
|
|
520
|
+
return undefined;
|
|
482
521
|
resolvedName = input;
|
|
483
522
|
}
|
|
484
523
|
}
|
|
485
524
|
let keychain = createKeychain(resolvedName);
|
|
486
525
|
while (await keychain.get()) {
|
|
526
|
+
if (structured)
|
|
527
|
+
return c.error({
|
|
528
|
+
code: 'ACCOUNT_EXISTS',
|
|
529
|
+
message: `Account "${resolvedName}" already exists.`,
|
|
530
|
+
exitCode: 1,
|
|
531
|
+
});
|
|
487
532
|
process.stderr.write(`${pc.dim(`Account "${resolvedName}" already exists.`)}\n\n`);
|
|
488
533
|
const input = await prompt('Enter different name');
|
|
489
534
|
if (!input)
|
|
490
|
-
return;
|
|
535
|
+
return undefined;
|
|
491
536
|
resolvedName = input;
|
|
492
537
|
keychain = createKeychain(resolvedName);
|
|
493
538
|
}
|
|
@@ -497,16 +542,18 @@ const account = Cli.create('account', {
|
|
|
497
542
|
const accounts = await createKeychain().list();
|
|
498
543
|
if (accounts.length === 1)
|
|
499
544
|
createDefaultStore().set(resolvedName);
|
|
500
|
-
console.log(`Account "${resolvedName}" saved to keychain.`);
|
|
501
545
|
const explorerUrl = tempoMainnet.blockExplorers?.default?.url;
|
|
502
546
|
const addrDisplay = explorerUrl
|
|
503
547
|
? link(`${explorerUrl}/address/${acct.address}`, acct.address)
|
|
504
548
|
: acct.address;
|
|
505
|
-
console.log(pc.dim(`Address ${addrDisplay}`));
|
|
506
549
|
const rpcUrl = resolveRpcUrl(c.options.rpcUrl);
|
|
507
550
|
resolveChain({ rpcUrl })
|
|
508
551
|
.then((chain) => createClient({ chain, transport: http(rpcUrl) }))
|
|
509
552
|
.then((client) => import('viem/tempo').then(({ Actions }) => Actions.faucet.fund(client, { account: acct }).catch(() => { })));
|
|
553
|
+
return outputResult(c, { address: acct.address, name: resolvedName }, () => {
|
|
554
|
+
console.log(`Account "${resolvedName}" saved to keychain.`);
|
|
555
|
+
console.log(pc.dim(`Address ${addrDisplay}`));
|
|
556
|
+
});
|
|
510
557
|
},
|
|
511
558
|
})
|
|
512
559
|
.command('default', {
|
|
@@ -514,6 +561,7 @@ const account = Cli.create('account', {
|
|
|
514
561
|
options: z.object({
|
|
515
562
|
account: z.string().describe('Account name'),
|
|
516
563
|
}),
|
|
564
|
+
output: z.object({ name: z.string() }),
|
|
517
565
|
alias: { account: 'a' },
|
|
518
566
|
async run(c) {
|
|
519
567
|
const accountName = c.options.account;
|
|
@@ -527,8 +575,9 @@ const account = Cli.create('account', {
|
|
|
527
575
|
});
|
|
528
576
|
}
|
|
529
577
|
createDefaultStore().set(accountName);
|
|
530
|
-
|
|
531
|
-
|
|
578
|
+
return outputResult(c, { name: accountName }, () => {
|
|
579
|
+
console.log(`Default account set to "${accountName}"`);
|
|
580
|
+
});
|
|
532
581
|
}
|
|
533
582
|
const key = await createKeychain(accountName).get();
|
|
534
583
|
if (!key) {
|
|
@@ -539,7 +588,9 @@ const account = Cli.create('account', {
|
|
|
539
588
|
});
|
|
540
589
|
}
|
|
541
590
|
createDefaultStore().set(accountName);
|
|
542
|
-
|
|
591
|
+
return outputResult(c, { name: accountName }, () => {
|
|
592
|
+
console.log(`Default account set to "${accountName}"`);
|
|
593
|
+
});
|
|
543
594
|
},
|
|
544
595
|
})
|
|
545
596
|
.command('delete', {
|
|
@@ -548,6 +599,7 @@ const account = Cli.create('account', {
|
|
|
548
599
|
account: z.string().describe('Account name'),
|
|
549
600
|
yes: z.boolean().optional().describe('DANGER!! Skip confirmation prompts'),
|
|
550
601
|
}),
|
|
602
|
+
output: z.object({ defaultAccount: z.string().optional(), name: z.string() }),
|
|
551
603
|
alias: { account: 'a' },
|
|
552
604
|
async run(c) {
|
|
553
605
|
const keychain = createKeychain(c.options.account);
|
|
@@ -562,6 +614,12 @@ const account = Cli.create('account', {
|
|
|
562
614
|
const acct = privateKeyToAccount(key);
|
|
563
615
|
const balanceLines = await fetchBalanceLines(acct.address, { includeTestnet: false });
|
|
564
616
|
if (!c.options.yes) {
|
|
617
|
+
if (shouldReturnStructured(c))
|
|
618
|
+
return c.error({
|
|
619
|
+
code: 'CONFIRMATION_REQUIRED',
|
|
620
|
+
message: 'Pass --yes to delete an account in structured mode.',
|
|
621
|
+
exitCode: 2,
|
|
622
|
+
});
|
|
565
623
|
const explorerUrl = tempoMainnet.blockExplorers?.default?.url;
|
|
566
624
|
const addrDisplay = explorerUrl
|
|
567
625
|
? link(`${explorerUrl}/address/${acct.address}`, acct.address)
|
|
@@ -574,22 +632,27 @@ const account = Cli.create('account', {
|
|
|
574
632
|
const confirmed = await confirm('Confirm delete?');
|
|
575
633
|
if (!confirmed) {
|
|
576
634
|
console.log('Canceled');
|
|
577
|
-
return;
|
|
635
|
+
return undefined;
|
|
578
636
|
}
|
|
579
637
|
}
|
|
580
638
|
await keychain.delete();
|
|
581
639
|
const currentDefault = createDefaultStore().get();
|
|
640
|
+
let defaultAccount;
|
|
582
641
|
if (currentDefault === c.options.account) {
|
|
583
642
|
const remaining = await createKeychain().list();
|
|
584
643
|
if (remaining.length > 0) {
|
|
585
|
-
|
|
586
|
-
|
|
644
|
+
defaultAccount = remaining[0];
|
|
645
|
+
createDefaultStore().set(defaultAccount);
|
|
587
646
|
}
|
|
588
647
|
else {
|
|
589
648
|
createDefaultStore().clear();
|
|
590
649
|
}
|
|
591
650
|
}
|
|
592
|
-
|
|
651
|
+
return outputResult(c, { defaultAccount, name: c.options.account }, () => {
|
|
652
|
+
if (defaultAccount)
|
|
653
|
+
console.log(`Default account set to "${defaultAccount}"`);
|
|
654
|
+
console.log(`Account "${c.options.account}" deleted`);
|
|
655
|
+
});
|
|
593
656
|
},
|
|
594
657
|
})
|
|
595
658
|
.command('fund', {
|
|
@@ -598,8 +661,10 @@ const account = Cli.create('account', {
|
|
|
598
661
|
account: z.string().optional().describe('Account name (env: MPPX_ACCOUNT)'),
|
|
599
662
|
rpcUrl: z.string().optional().describe('RPC endpoint (env: MPPX_RPC_URL)'),
|
|
600
663
|
}),
|
|
664
|
+
output: z.object({ account: z.string(), chain: z.string(), transactions: z.array(z.string()) }),
|
|
601
665
|
alias: { account: 'a', rpcUrl: 'r' },
|
|
602
666
|
async run(c) {
|
|
667
|
+
const structured = shouldReturnStructured(c);
|
|
603
668
|
const accountName = resolveAccountName(c.options.account);
|
|
604
669
|
const keychain = createKeychain(accountName);
|
|
605
670
|
const key = await keychain.get();
|
|
@@ -617,27 +682,40 @@ const account = Cli.create('account', {
|
|
|
617
682
|
const rpcUrl = resolveRpcUrl(c.options.rpcUrl);
|
|
618
683
|
const chain = await resolveChain({ rpcUrl });
|
|
619
684
|
const client = createClient({ chain, transport: http(rpcUrl) });
|
|
620
|
-
|
|
685
|
+
if (!structured)
|
|
686
|
+
console.log(`Funding "${accountName}" on ${chainName(chain)}`);
|
|
621
687
|
try {
|
|
622
688
|
const { Actions } = await import('viem/tempo');
|
|
623
689
|
const hashes = await Actions.faucet.fund(client, { account: acct });
|
|
624
690
|
const explorerUrl = chain.blockExplorers?.default?.url;
|
|
625
|
-
|
|
626
|
-
const
|
|
627
|
-
|
|
691
|
+
if (!structured) {
|
|
692
|
+
for (const hash of hashes) {
|
|
693
|
+
const label = explorerUrl ? link(`${explorerUrl}/tx/${hash}`, pc.gray(hash)) : hash;
|
|
694
|
+
console.log(` ${label}`);
|
|
695
|
+
}
|
|
628
696
|
}
|
|
629
697
|
const { waitForTransactionReceipt } = await import('viem/actions');
|
|
630
698
|
await Promise.all(hashes.map((hash) => waitForTransactionReceipt(client, { hash })));
|
|
631
|
-
|
|
699
|
+
return outputResult(c, { account: accountName, chain: chainName(chain), transactions: [...hashes] }, () => {
|
|
700
|
+
console.log('Funded successfully');
|
|
701
|
+
});
|
|
632
702
|
}
|
|
633
703
|
catch (err) {
|
|
704
|
+
if (structured)
|
|
705
|
+
return c.error({
|
|
706
|
+
code: 'FUNDING_FAILED',
|
|
707
|
+
message: err instanceof Error ? err.message : String(err),
|
|
708
|
+
exitCode: 1,
|
|
709
|
+
});
|
|
634
710
|
console.error('Funding failed:', err instanceof Error ? err.message : err);
|
|
711
|
+
return undefined;
|
|
635
712
|
}
|
|
636
713
|
},
|
|
637
714
|
})
|
|
638
715
|
.command('list', {
|
|
639
716
|
description: 'List all accounts',
|
|
640
|
-
|
|
717
|
+
output: z.object({ accounts: z.array(accountSummarySchema) }),
|
|
718
|
+
async run(c) {
|
|
641
719
|
const currentDefault = createDefaultStore().get();
|
|
642
720
|
const accounts = (await createKeychain().list()).sort();
|
|
643
721
|
const resolved = [];
|
|
@@ -658,21 +736,29 @@ const account = Cli.create('account', {
|
|
|
658
736
|
resolved.push({ name: tempoName, address: entry.wallet_address, source: 'tempo wallet' });
|
|
659
737
|
}
|
|
660
738
|
if (resolved.length === 0) {
|
|
661
|
-
|
|
662
|
-
|
|
739
|
+
return outputResult(c, { accounts: [] }, () => {
|
|
740
|
+
console.log(`No accounts found.`);
|
|
741
|
+
});
|
|
663
742
|
}
|
|
664
743
|
const explorerUrl = tempoMainnet.blockExplorers?.default?.url;
|
|
665
744
|
const maxWidth = Math.max(...resolved.map((e) => e.name.length + (e.name === currentDefault ? 1 : 0)));
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
745
|
+
return outputResult(c, {
|
|
746
|
+
accounts: resolved.map((entry) => ({
|
|
747
|
+
...entry,
|
|
748
|
+
...(entry.name === currentDefault ? { isDefault: true } : undefined),
|
|
749
|
+
})),
|
|
750
|
+
}, () => {
|
|
751
|
+
for (const entry of resolved) {
|
|
752
|
+
const isDefault = entry.name === currentDefault;
|
|
753
|
+
const label = isDefault ? `${entry.name}${pc.dim('*')}` : entry.name;
|
|
754
|
+
const width = entry.name.length + (isDefault ? 1 : 0);
|
|
755
|
+
const addrDisplay = explorerUrl
|
|
756
|
+
? link(`${explorerUrl}/address/${entry.address}`, entry.address)
|
|
757
|
+
: entry.address;
|
|
758
|
+
const sourceLabel = entry.source ? ` ${pc.dim(`(${entry.source})`)}` : '';
|
|
759
|
+
console.log(`${label}${' '.repeat(maxWidth - width + 2)}${pc.dim(addrDisplay)}${sourceLabel}`);
|
|
760
|
+
}
|
|
761
|
+
});
|
|
676
762
|
},
|
|
677
763
|
})
|
|
678
764
|
.command('export', {
|
|
@@ -680,6 +766,7 @@ const account = Cli.create('account', {
|
|
|
680
766
|
options: z.object({
|
|
681
767
|
account: z.string().optional().describe('Account name (env: MPPX_ACCOUNT)'),
|
|
682
768
|
}),
|
|
769
|
+
output: z.object({ privateKey: z.string() }),
|
|
683
770
|
alias: { account: 'a' },
|
|
684
771
|
async run(c) {
|
|
685
772
|
const accountName = resolveAccountName(c.options.account);
|
|
@@ -701,7 +788,9 @@ const account = Cli.create('account', {
|
|
|
701
788
|
else
|
|
702
789
|
return c.error({ code: 'ACCOUNT_NOT_FOUND', message: 'No account found.', exitCode: 69 });
|
|
703
790
|
}
|
|
704
|
-
|
|
791
|
+
return outputResult(c, { privateKey: key }, () => {
|
|
792
|
+
console.log(key);
|
|
793
|
+
});
|
|
705
794
|
},
|
|
706
795
|
})
|
|
707
796
|
.command('view', {
|
|
@@ -710,6 +799,7 @@ const account = Cli.create('account', {
|
|
|
710
799
|
account: z.string().optional().describe('Account name (env: MPPX_ACCOUNT)'),
|
|
711
800
|
rpcUrl: z.string().optional().describe('RPC endpoint (env: MPPX_RPC_URL)'),
|
|
712
801
|
}),
|
|
802
|
+
output: accountViewSchema,
|
|
713
803
|
alias: { account: 'a', rpcUrl: 'r' },
|
|
714
804
|
async run(c) {
|
|
715
805
|
const accountName = resolveAccountName(c.options.account);
|
|
@@ -729,13 +819,19 @@ const account = Cli.create('account', {
|
|
|
729
819
|
const addrDisplay = explorerUrl
|
|
730
820
|
? link(`${explorerUrl}/address/${address}`, address)
|
|
731
821
|
: address;
|
|
732
|
-
console.log(`${pc.dim('Address')} ${addrDisplay}`);
|
|
733
822
|
const balanceLines = await fetchBalanceLines(address, chain && rpcUrl ? { chain, rpcUrl } : undefined);
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
823
|
+
return outputResult(c, {
|
|
824
|
+
address,
|
|
825
|
+
balances: balanceLines,
|
|
826
|
+
name: accountName,
|
|
827
|
+
type: `${tempoEntry.wallet_type} (tempo wallet)`,
|
|
828
|
+
}, () => {
|
|
829
|
+
console.log(`${pc.dim('Address')} ${addrDisplay}`);
|
|
830
|
+
for (let i = 0; i < balanceLines.length; i++)
|
|
831
|
+
console.log(`${pc.dim(i === 0 ? 'Balance' : ' ')} ${balanceLines[i]}`);
|
|
832
|
+
console.log(`${pc.dim('Name')} ${accountName}`);
|
|
833
|
+
console.log(`${pc.dim('Type')} ${tempoEntry.wallet_type} ${pc.dim('(tempo wallet)')}`);
|
|
834
|
+
});
|
|
739
835
|
}
|
|
740
836
|
const keychain = createKeychain(accountName);
|
|
741
837
|
const key = await keychain.get();
|
|
@@ -756,11 +852,13 @@ const account = Cli.create('account', {
|
|
|
756
852
|
const addrDisplay = explorerUrl
|
|
757
853
|
? link(`${explorerUrl}/address/${acct.address}`, acct.address)
|
|
758
854
|
: acct.address;
|
|
759
|
-
console.log(`${pc.dim('Address')} ${addrDisplay}`);
|
|
760
855
|
const balanceLines = await fetchBalanceLines(acct.address, chain && rpcUrl ? { chain, rpcUrl } : undefined);
|
|
761
|
-
|
|
762
|
-
console.log(`${pc.dim(
|
|
763
|
-
|
|
856
|
+
return outputResult(c, { address: acct.address, balances: balanceLines, name: accountName }, () => {
|
|
857
|
+
console.log(`${pc.dim('Address')} ${addrDisplay}`);
|
|
858
|
+
for (let i = 0; i < balanceLines.length; i++)
|
|
859
|
+
console.log(`${pc.dim(i === 0 ? 'Balance' : ' ')} ${balanceLines[i]}`);
|
|
860
|
+
console.log(`${pc.dim('Name')} ${accountName}`);
|
|
861
|
+
});
|
|
764
862
|
},
|
|
765
863
|
});
|
|
766
864
|
const sign = Cli.create('sign', {
|
|
@@ -783,6 +881,7 @@ const sign = Cli.create('sign', {
|
|
|
783
881
|
.optional()
|
|
784
882
|
.describe('RPC endpoint, defaults to public RPC for chain (env: MPPX_RPC_URL)'),
|
|
785
883
|
}),
|
|
884
|
+
output: z.object({ authorization: z.string() }),
|
|
786
885
|
alias: {
|
|
787
886
|
account: 'a',
|
|
788
887
|
challenge: 'C',
|
|
@@ -792,7 +891,7 @@ const sign = Cli.create('sign', {
|
|
|
792
891
|
},
|
|
793
892
|
async run(c) {
|
|
794
893
|
const raw = c.options.challenge ||
|
|
795
|
-
(
|
|
894
|
+
(canReadCommandStdin()
|
|
796
895
|
? await new Promise((resolve, reject) => {
|
|
797
896
|
let data = '';
|
|
798
897
|
process.stdin.setEncoding('utf-8');
|
|
@@ -823,7 +922,7 @@ const sign = Cli.create('sign', {
|
|
|
823
922
|
}
|
|
824
923
|
if (c.options.dryRun) {
|
|
825
924
|
process.stderr.write('Challenge is valid.\n');
|
|
826
|
-
return;
|
|
925
|
+
return undefined;
|
|
827
926
|
}
|
|
828
927
|
const loaded = await loadConfig(c.options.config);
|
|
829
928
|
const selected = selectChallenge(challenges, loaded?.config);
|
|
@@ -870,12 +969,9 @@ const sign = Cli.create('sign', {
|
|
|
870
969
|
exitCode: 2,
|
|
871
970
|
});
|
|
872
971
|
}
|
|
873
|
-
|
|
874
|
-
console.log(JSON.stringify({ authorization: credential }));
|
|
875
|
-
}
|
|
876
|
-
else {
|
|
972
|
+
return outputResult(c, { authorization: credential }, () => {
|
|
877
973
|
console.log(credential);
|
|
878
|
-
}
|
|
974
|
+
});
|
|
879
975
|
},
|
|
880
976
|
});
|
|
881
977
|
const init = Cli.create('init', {
|
|
@@ -883,6 +979,7 @@ const init = Cli.create('init', {
|
|
|
883
979
|
options: z.object({
|
|
884
980
|
force: z.boolean().optional().describe('Overwrite existing config file'),
|
|
885
981
|
}),
|
|
982
|
+
output: z.object({ file: z.string() }),
|
|
886
983
|
alias: { force: 'f' },
|
|
887
984
|
async run(c) {
|
|
888
985
|
const cwd = process.cwd();
|
|
@@ -915,7 +1012,9 @@ export default defineConfig({
|
|
|
915
1012
|
})
|
|
916
1013
|
`;
|
|
917
1014
|
fs.writeFileSync(dest, template);
|
|
918
|
-
|
|
1015
|
+
return outputResult(c, { file: dest }, () => {
|
|
1016
|
+
console.log(`Created ${filename}`);
|
|
1017
|
+
});
|
|
919
1018
|
},
|
|
920
1019
|
});
|
|
921
1020
|
const discover = Cli.create('discover', {
|
|
@@ -929,6 +1028,7 @@ const discover = Cli.create('discover', {
|
|
|
929
1028
|
options: z.object({
|
|
930
1029
|
output: z.string().optional().describe('Write output to a file instead of stdout'),
|
|
931
1030
|
}),
|
|
1031
|
+
output: z.record(z.string(), z.unknown()),
|
|
932
1032
|
alias: { output: 'o' },
|
|
933
1033
|
async run(c) {
|
|
934
1034
|
const modulePath = path.resolve(c.args.module);
|
|
@@ -974,9 +1074,12 @@ const discover = Cli.create('discover', {
|
|
|
974
1074
|
const outPath = path.resolve(c.options.output);
|
|
975
1075
|
fs.writeFileSync(outPath, `${json}\n`);
|
|
976
1076
|
process.stderr.write(`Wrote ${outPath}\n`);
|
|
1077
|
+
return outputResult(c, doc, () => { });
|
|
977
1078
|
}
|
|
978
1079
|
else {
|
|
979
|
-
|
|
1080
|
+
return outputResult(c, doc, () => {
|
|
1081
|
+
console.log(json);
|
|
1082
|
+
});
|
|
980
1083
|
}
|
|
981
1084
|
},
|
|
982
1085
|
})
|
|
@@ -985,6 +1088,12 @@ const discover = Cli.create('discover', {
|
|
|
985
1088
|
args: z.object({
|
|
986
1089
|
input: z.string().describe('Path or URL to a discovery document'),
|
|
987
1090
|
}),
|
|
1091
|
+
output: z.object({
|
|
1092
|
+
errorCount: z.number(),
|
|
1093
|
+
issues: z.array(discoveryIssueSchema),
|
|
1094
|
+
valid: z.boolean(),
|
|
1095
|
+
warningCount: z.number(),
|
|
1096
|
+
}),
|
|
988
1097
|
async run(c) {
|
|
989
1098
|
const input = c.args.input;
|
|
990
1099
|
let raw;
|
|
@@ -1055,8 +1164,9 @@ const discover = Cli.create('discover', {
|
|
|
1055
1164
|
});
|
|
1056
1165
|
}
|
|
1057
1166
|
const issues = validateDiscovery(doc);
|
|
1058
|
-
|
|
1059
|
-
|
|
1167
|
+
if (!shouldReturnStructured(c))
|
|
1168
|
+
for (const issue of issues)
|
|
1169
|
+
console.log(`[${issue.severity}] ${issue.path}: ${issue.message}`);
|
|
1060
1170
|
const errorCount = issues.filter((issue) => issue.severity === 'error').length;
|
|
1061
1171
|
const warningCount = issues.filter((issue) => issue.severity === 'warning').length;
|
|
1062
1172
|
if (errorCount > 0) {
|
|
@@ -1066,9 +1176,11 @@ const discover = Cli.create('discover', {
|
|
|
1066
1176
|
exitCode: 1,
|
|
1067
1177
|
});
|
|
1068
1178
|
}
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1179
|
+
return outputResult(c, { errorCount, issues, valid: true, warningCount }, () => {
|
|
1180
|
+
console.log(warningCount > 0
|
|
1181
|
+
? `Discovery document is valid with ${warningCount} warning(s).`
|
|
1182
|
+
: 'Discovery document is valid.');
|
|
1183
|
+
});
|
|
1072
1184
|
},
|
|
1073
1185
|
});
|
|
1074
1186
|
cli.command(account);
|