rdx-cli 0.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 ADDED
@@ -0,0 +1,95 @@
1
+ # rdx-cli
2
+
3
+
4
+ <p align="center">
5
+ <img src="./assets/agent-mascot.png" alt="rdx mascot" width="220">
6
+ </p>
7
+
8
+ Agent-first Radix transaction workflow CLI. The package publishes the `rdx` executable for preparing, inspecting, signing-orchestrating, notarizing, submitting, and tracking Radix Transaction Manifest V2 workflows from files.
9
+
10
+ `rdx` is not a consumer wallet and does not take key custody. It never stores, accepts, or derives private keys. Participants sign requested `hash.hex` values outside the CLI and return filled signature templates or signature files.
11
+
12
+ ## Installation
13
+
14
+ ```bash
15
+ npm install -g rdx-cli
16
+ ```
17
+
18
+ Or run from a project script after adding `rdx-cli` as a dependency.
19
+
20
+ ## Get Started
21
+
22
+ ```bash
23
+ rdx llm
24
+ rdx --help
25
+ rdx config show
26
+ ```
27
+
28
+ `rdx llm` prints the embedded Markdown guide for coding agents. Use it as the canonical operational quickstart before automating transaction workflows.
29
+
30
+ ## Safety Model
31
+
32
+ - Workflow commands are non-interactive and print JSON by default.
33
+ - `rdx` defaults to Mainnet; verify the resolved network with `rdx config show` before `tx prepare`.
34
+ - Prepared transaction artifacts are network-bound. Do not prepare on one network and submit on another.
35
+ - v1 workflow files support Ed25519 keys and signatures only.
36
+ - Signing is out of band: sign only the `hash.hex` in generated signing requests.
37
+
38
+ ## Transaction Lifecycle
39
+
40
+ ```bash
41
+ rdx config show
42
+ rdx tx prepare --manifest ./tx/root.rtm --notary-file ./tx/notary.json
43
+ rdx tx add-signatures txid_example --file ./tx/signatures/intent-signature.json
44
+ rdx tx notarize txid_example
45
+ rdx tx add-signatures txid_example --file ./tx/signatures/notary-signature.json
46
+ rdx tx submit txid_example
47
+ rdx tx status txid_example
48
+ ```
49
+
50
+ For direct child subintents, provide a subintents workflow file during preparation:
51
+
52
+ ```bash
53
+ rdx tx prepare --manifest ./tx/root.rtm --subintents ./tx/subintents.json --notary-file ./tx/notary.json
54
+ ```
55
+
56
+ Use command JSON output for exact artifact paths. Common artifacts include `prepared.json`, `transactionIntent.json`, `staticAnalysis.json`, `signatures.json`, copied manifests, `notarizedTransaction.hex`, and `submitResult.json`.
57
+
58
+ ## Discovery Commands
59
+
60
+ ```bash
61
+ rdx template print subintents
62
+ rdx template print signing-request
63
+ rdx template print signature-template
64
+ rdx template print signature-file
65
+ rdx tx path txid_example
66
+ rdx tx list
67
+ rdx tx list --pattern root.rtm
68
+ ```
69
+
70
+ Use `rdx template print ...` for live workflow file shapes. This README intentionally avoids duplicating config or workflow schemas to reduce drift.
71
+
72
+ ## Account Reads
73
+
74
+ ```bash
75
+ rdx account show account_rdx1...
76
+ rdx account balance account_rdx1...
77
+ rdx account derive --public-key 1111111111111111111111111111111111111111111111111111111111111111
78
+ rdx tx history account_rdx1... --limit 10
79
+ rdx tx status txid_example
80
+ ```
81
+
82
+ Account read commands query Gateway state and do not require signing.
83
+ `account derive` is offline: it derives the virtual account address for the resolved network and does not prove the account exists on-ledger.
84
+
85
+ ## Current Scope
86
+
87
+ - Transaction Manifest V2 workflows only.
88
+ - Root transaction plus direct child subintents only.
89
+ - Ed25519 CLI key/signature workflow files only.
90
+ - Out-of-band signing only; no private-key CLI flags or keystore.
91
+ - No consumer wallet UX, browser wallet pairing, hardware wallet integration, or high-level transfer builders.
92
+
93
+ ## License
94
+
95
+ MIT
@@ -0,0 +1 @@
1
+ export { };
@@ -0,0 +1,95 @@
1
+ #!/usr/bin/env node
2
+ import { Kt as renderJson, t as cli } from "../cli-n0bR-cOj.js";
3
+ import { Console, Data, Effect, Option, Schema } from "effect";
4
+ import { FileSystem, Path } from "@effect/platform";
5
+ import { NodeContext, NodeRuntime } from "@effect/platform-node";
6
+ import { ValidationError } from "@effect/cli";
7
+ import { Terminal } from "@effect/platform/Terminal";
8
+
9
+ //#region src/bin/rdx.ts
10
+ const CliBuiltInRenderFlagSchema = Schema.Literal("--help", "-h", "--version", "--wizard", "--completions");
11
+ const shouldRenderCliTerminal = (argv) => argv.some(Schema.is(CliBuiltInRenderFlagSchema));
12
+ const quietTerminal = {
13
+ columns: Effect.succeed(80),
14
+ rows: Effect.succeed(24),
15
+ isTTY: Effect.succeed(false),
16
+ readInput: Effect.dieMessage("rdx is non-interactive"),
17
+ readLine: Effect.dieMessage("rdx is non-interactive"),
18
+ display: () => Effect.void
19
+ };
20
+ let hasSuppressedCliValidationText = false;
21
+ const suppressCliValidationText = (argv) => Effect.sync(() => {
22
+ if (shouldRenderCliTerminal(argv) || hasSuppressedCliValidationText) return;
23
+ hasSuppressedCliValidationText = true;
24
+ const stdoutWrite = process.stdout.write.bind(process.stdout);
25
+ const stderrWrite = process.stderr.write.bind(process.stderr);
26
+ const shouldSuppressCliValidationText = (chunk) => typeof chunk === "string" && (chunk.startsWith("Invalid ") || chunk.startsWith("Missing ") || chunk.startsWith("Expected "));
27
+ process.stdout.write = ((chunk, ...args) => shouldSuppressCliValidationText(chunk) ? true : stdoutWrite(chunk, ...args));
28
+ process.stderr.write = ((chunk, ...args) => shouldSuppressCliValidationText(chunk) ? true : stderrWrite(chunk, ...args));
29
+ });
30
+ const CliValidationTextSchema = Schema.Struct({ error: Schema.Struct({ value: Schema.Struct({ value: Schema.String }) }) });
31
+ const CodedErrorSchema = Schema.Struct({ code: Schema.String });
32
+ const TaggedErrorSchema = Schema.Struct({
33
+ _tag: Schema.String,
34
+ code: Schema.optional(Schema.String),
35
+ path: Schema.optional(Schema.String),
36
+ subintentId: Schema.optional(Schema.String),
37
+ reason: Schema.optional(Schema.Unknown)
38
+ });
39
+ const decodeUnknownOption = (schema, value) => Option.getOrUndefined(Schema.decodeUnknownOption(schema)(value));
40
+ var CliFailure = class extends Data.TaggedError("CliFailure") {};
41
+ const reasonMessage = (reason) => {
42
+ if (reason === void 0) return "";
43
+ if (reason instanceof Error) return `: ${reason.message}`;
44
+ if (typeof reason === "string") return `: ${reason}`;
45
+ return `: ${renderJson(reason)}`;
46
+ };
47
+ const validationMessage = (error) => {
48
+ const cliValidationText = decodeUnknownOption(CliValidationTextSchema, error);
49
+ if (cliValidationText) return cliValidationText.error.value.value;
50
+ const taggedError = decodeUnknownOption(TaggedErrorSchema, error);
51
+ if (taggedError) {
52
+ const path = taggedError.path ? ` at ${taggedError.path}` : "";
53
+ const subintentId = taggedError.subintentId ? ` for ${taggedError.subintentId}` : "";
54
+ const reason = reasonMessage(taggedError.reason);
55
+ return [taggedError._tag, taggedError.code].filter(Boolean).join(" ") + subintentId + path + reason;
56
+ }
57
+ return error instanceof Error ? error.message : String(error);
58
+ };
59
+ const validationCode = (error, message) => {
60
+ if (ValidationError.isValidationError(error) && ValidationError.isMissingSubcommand(error) || message.startsWith("Invalid subcommand")) return "UNKNOWN_COMMAND";
61
+ const codedError = decodeUnknownOption(CodedErrorSchema, error);
62
+ if (codedError) return codedError.code;
63
+ const taggedError = decodeUnknownOption(TaggedErrorSchema, error);
64
+ if (taggedError) return taggedError._tag.replace(/([a-z])([A-Z])/g, "$1_$2").toUpperCase();
65
+ return "CLI_VALIDATION_ERROR";
66
+ };
67
+ const normalizeCliFailure = (error) => {
68
+ const message = validationMessage(error);
69
+ return new CliFailure({
70
+ code: validationCode(error, message),
71
+ message
72
+ });
73
+ };
74
+ const reportCliFailure = (failure) => Console.error(renderJson({
75
+ type: "error",
76
+ code: failure.code,
77
+ message: failure.message
78
+ })).pipe(Effect.zipRight(Effect.sync(() => {
79
+ process.exitCode = 64;
80
+ })));
81
+ var RdxCliRuntime = class extends Effect.Service()("RdxCliRuntime", {
82
+ accessors: true,
83
+ effect: Effect.gen(function* () {
84
+ const fileSystem = yield* FileSystem.FileSystem;
85
+ const path = yield* Path.Path;
86
+ const terminal = yield* Terminal;
87
+ return { run: (argv) => suppressCliValidationText(argv).pipe(Effect.zipRight(Effect.suspend(() => cli([...argv])).pipe(Effect.provideService(FileSystem.FileSystem, fileSystem), Effect.provideService(Path.Path, path), Effect.provideService(Terminal, shouldRenderCliTerminal(argv) ? terminal : quietTerminal))), Effect.catchAll((error) => reportCliFailure(normalizeCliFailure(error)))) };
88
+ }),
89
+ dependencies: [NodeContext.layer]
90
+ }) {};
91
+ RdxCliRuntime.run(process.argv).pipe(Effect.provide(RdxCliRuntime.Default), NodeRuntime.runMain);
92
+
93
+ //#endregion
94
+ export { };
95
+ //# sourceMappingURL=rdx.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rdx.js","names":[],"sources":["../../src/bin/rdx.ts"],"sourcesContent":["#!/usr/bin/env node\nimport { ValidationError } from '@effect/cli';\nimport { NodeContext, NodeRuntime } from '@effect/platform-node';\nimport { FileSystem, Path } from '@effect/platform';\nimport {\n Terminal,\n type Terminal as TerminalService,\n} from '@effect/platform/Terminal';\nimport { Console, Data, Effect, Option, Schema } from 'effect';\nimport { cli } from '../cli';\nimport { renderJson } from '../json';\n\nconst CliBuiltInRenderFlagSchema = Schema.Literal(\n '--help',\n '-h',\n '--version',\n '--wizard',\n '--completions',\n);\nconst shouldRenderCliTerminal = (argv: ReadonlyArray<string>) =>\n argv.some(Schema.is(CliBuiltInRenderFlagSchema));\n\nconst quietTerminal = {\n columns: Effect.succeed(80),\n rows: Effect.succeed(24),\n isTTY: Effect.succeed(false),\n readInput: Effect.dieMessage('rdx is non-interactive'),\n readLine: Effect.dieMessage('rdx is non-interactive'),\n display: () => Effect.void,\n} as TerminalService;\n\nlet hasSuppressedCliValidationText = false;\n\nconst suppressCliValidationText = (argv: ReadonlyArray<string>) =>\n Effect.sync(() => {\n if (shouldRenderCliTerminal(argv) || hasSuppressedCliValidationText) {\n return;\n }\n\n hasSuppressedCliValidationText = true;\n const stdoutWrite = process.stdout.write.bind(process.stdout);\n const stderrWrite = process.stderr.write.bind(process.stderr);\n const shouldSuppressCliValidationText = (chunk: unknown) =>\n typeof chunk === 'string' &&\n (chunk.startsWith('Invalid ') ||\n chunk.startsWith('Missing ') ||\n chunk.startsWith('Expected '));\n\n process.stdout.write = ((chunk: unknown, ...args: unknown[]) =>\n shouldSuppressCliValidationText(chunk)\n ? true\n : stdoutWrite(\n chunk as never,\n ...(args as never[]),\n )) as typeof process.stdout.write;\n process.stderr.write = ((chunk: unknown, ...args: unknown[]) =>\n shouldSuppressCliValidationText(chunk)\n ? true\n : stderrWrite(\n chunk as never,\n ...(args as never[]),\n )) as typeof process.stderr.write;\n });\n\nconst CliValidationTextSchema = Schema.Struct({\n error: Schema.Struct({\n value: Schema.Struct({\n value: Schema.String,\n }),\n }),\n});\n\nconst CodedErrorSchema = Schema.Struct({\n code: Schema.String,\n});\n\nconst TaggedErrorSchema = Schema.Struct({\n _tag: Schema.String,\n code: Schema.optional(Schema.String),\n path: Schema.optional(Schema.String),\n subintentId: Schema.optional(Schema.String),\n reason: Schema.optional(Schema.Unknown),\n});\n\nconst decodeUnknownOption = <A>(schema: Schema.Schema<A>, value: unknown) =>\n Option.getOrUndefined(Schema.decodeUnknownOption(schema)(value));\n\nclass CliFailure extends Data.TaggedError('CliFailure')<{\n code: string;\n message: string;\n}> {}\n\nconst reasonMessage = (reason: unknown) => {\n if (reason === undefined) {\n return '';\n }\n\n if (reason instanceof Error) {\n return `: ${reason.message}`;\n }\n\n if (typeof reason === 'string') {\n return `: ${reason}`;\n }\n\n return `: ${renderJson(reason)}`;\n};\n\nconst validationMessage = (error: unknown) => {\n const cliValidationText = decodeUnknownOption(CliValidationTextSchema, error);\n if (cliValidationText) {\n return cliValidationText.error.value.value;\n }\n\n const taggedError = decodeUnknownOption(TaggedErrorSchema, error);\n if (taggedError) {\n const path = taggedError.path ? ` at ${taggedError.path}` : '';\n const subintentId = taggedError.subintentId\n ? ` for ${taggedError.subintentId}`\n : '';\n const reason = reasonMessage(taggedError.reason);\n\n return (\n [taggedError._tag, taggedError.code].filter(Boolean).join(' ') +\n subintentId +\n path +\n reason\n );\n }\n\n return error instanceof Error ? error.message : String(error);\n};\n\nconst validationCode = (error: unknown, message: string) => {\n if (\n (ValidationError.isValidationError(error) &&\n ValidationError.isMissingSubcommand(error)) ||\n message.startsWith('Invalid subcommand')\n ) {\n return 'UNKNOWN_COMMAND';\n }\n\n const codedError = decodeUnknownOption(CodedErrorSchema, error);\n if (codedError) {\n return codedError.code;\n }\n\n const taggedError = decodeUnknownOption(TaggedErrorSchema, error);\n if (taggedError) {\n return taggedError._tag.replace(/([a-z])([A-Z])/g, '$1_$2').toUpperCase();\n }\n\n return 'CLI_VALIDATION_ERROR';\n};\n\nconst normalizeCliFailure = (error: unknown) => {\n const message = validationMessage(error);\n\n return new CliFailure({\n code: validationCode(error, message),\n message,\n });\n};\n\nconst reportCliFailure = (failure: CliFailure) =>\n Console.error(\n renderJson({\n type: 'error',\n code: failure.code,\n message: failure.message,\n }),\n ).pipe(\n Effect.zipRight(\n Effect.sync(() => {\n process.exitCode = 64;\n }),\n ),\n );\n\nclass RdxCliRuntime extends Effect.Service<RdxCliRuntime>()('RdxCliRuntime', {\n accessors: true,\n effect: Effect.gen(function* () {\n const fileSystem = yield* FileSystem.FileSystem;\n const path = yield* Path.Path;\n const terminal = yield* Terminal;\n\n return {\n run: (argv: ReadonlyArray<string>) =>\n suppressCliValidationText(argv).pipe(\n Effect.zipRight(\n Effect.suspend(() => cli([...argv])).pipe(\n Effect.provideService(FileSystem.FileSystem, fileSystem),\n Effect.provideService(Path.Path, path),\n Effect.provideService(\n Terminal,\n shouldRenderCliTerminal(argv) ? terminal : quietTerminal,\n ),\n ),\n ),\n Effect.catchAll((error) =>\n reportCliFailure(normalizeCliFailure(error)),\n ),\n ),\n };\n }),\n dependencies: [NodeContext.layer],\n}) {}\n\nRdxCliRuntime.run(process.argv).pipe(\n Effect.provide(RdxCliRuntime.Default),\n NodeRuntime.runMain,\n);\n"],"mappings":"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"}