polkadot-cli 1.7.0 → 1.8.1
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 +58 -1
- package/dist/cli.mjs +215 -33
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -21,6 +21,7 @@ Ships with Polkadot and all system parachains preconfigured with multiple fallba
|
|
|
21
21
|
- ✅ Runtime API calls — `dot apis.Core.version`
|
|
22
22
|
- ✅ Batteries included — all system parachains and testnets already setup to be used
|
|
23
23
|
- ✅ File-based commands — run any command from a YAML/JSON file with variable substitution
|
|
24
|
+
- ✅ Parachain sovereign accounts — derive child and sibling addresses from a parachain ID
|
|
24
25
|
|
|
25
26
|
### Preconfigured chains
|
|
26
27
|
|
|
@@ -496,6 +497,28 @@ dot tx Balances.transfer_keep_alive 5FHneW46... 1000000000000 --encode
|
|
|
496
497
|
dot tx Sudo.sudo $(dot tx System.remark 0xcafe --encode) --from alice
|
|
497
498
|
```
|
|
498
499
|
|
|
500
|
+
#### Decode call data to YAML / JSON
|
|
501
|
+
|
|
502
|
+
Decode a hex-encoded call into a YAML or JSON file that is compatible with [file-based commands](#file-based-commands). This is useful for inspecting opaque call data, sharing human-readable transaction definitions, or editing parameters before re-submitting. Works offline from cached metadata and does not require `--from`.
|
|
503
|
+
|
|
504
|
+
```bash
|
|
505
|
+
# Decode a raw hex call to YAML
|
|
506
|
+
dot tx.0x0001076465616462656566 --yaml
|
|
507
|
+
|
|
508
|
+
# Decode a raw hex call to JSON
|
|
509
|
+
dot tx.0x0001076465616462656566 --json
|
|
510
|
+
|
|
511
|
+
# Encode a named call and output as YAML
|
|
512
|
+
dot tx.System.remark 0xdeadbeef --yaml
|
|
513
|
+
|
|
514
|
+
# Round-trip: encode to hex, decode to YAML, re-encode from file
|
|
515
|
+
dot tx.System.remark 0xdeadbeef --encode # 0x0001076465616462656566
|
|
516
|
+
dot tx.0x0001076465616462656566 --yaml > remark.yaml
|
|
517
|
+
dot ./remark.yaml --encode # same hex
|
|
518
|
+
```
|
|
519
|
+
|
|
520
|
+
`--yaml` / `--json` are mutually exclusive with each other and with `--encode` and `--dry-run`.
|
|
521
|
+
|
|
499
522
|
Both dry-run and submission display the encoded call hex and a decoded human-readable form:
|
|
500
523
|
|
|
501
524
|
```
|
|
@@ -750,7 +773,15 @@ tx:
|
|
|
750
773
|
value: ${AMOUNT}
|
|
751
774
|
```
|
|
752
775
|
|
|
753
|
-
|
|
776
|
+
Hex values passed via `--var` are preserved as-is, including leading zeros. This is important for encoded call data in XCM `Transact` instructions or similar byte-array fields:
|
|
777
|
+
|
|
778
|
+
```bash
|
|
779
|
+
# Encode a remark, then embed it in an XCM Transact via --var
|
|
780
|
+
CALL=$(dot tx.System.remark 0xdead --encode)
|
|
781
|
+
dot ./xcm-transact.yaml --var CALL=$CALL --encode
|
|
782
|
+
```
|
|
783
|
+
|
|
784
|
+
All existing flags work with file input — `--chain` overrides the file's `chain:` field, `--from`, `--dry-run`, `--encode`, `--yaml`, `--json`, `--output`, etc. behave identically to inline commands.
|
|
754
785
|
|
|
755
786
|
### Compute hashes
|
|
756
787
|
|
|
@@ -775,6 +806,32 @@ dot hash blake2b256 0xdeadbeef --output json
|
|
|
775
806
|
|
|
776
807
|
Run `dot hash` with no arguments to see all available algorithms.
|
|
777
808
|
|
|
809
|
+
### Parachain sovereign accounts
|
|
810
|
+
|
|
811
|
+
Derive the sovereign account addresses for a parachain. These are deterministic accounts derived from a parachain ID — no chain connection required.
|
|
812
|
+
|
|
813
|
+
- **Child** accounts represent a parachain on the relay chain (prefix `"para"`)
|
|
814
|
+
- **Sibling** accounts represent a parachain on another parachain (prefix `"sibl"`)
|
|
815
|
+
|
|
816
|
+
```bash
|
|
817
|
+
# Show both child and sibling accounts
|
|
818
|
+
dot parachain 1000
|
|
819
|
+
|
|
820
|
+
# Show only the child (relay chain) account
|
|
821
|
+
dot parachain 2004 --type child
|
|
822
|
+
|
|
823
|
+
# Show only the sibling (parachain-to-parachain) account
|
|
824
|
+
dot parachain 2004 --type sibling
|
|
825
|
+
|
|
826
|
+
# Use Polkadot SS58 prefix (default: 42)
|
|
827
|
+
dot parachain 1000 --prefix 0
|
|
828
|
+
|
|
829
|
+
# JSON output
|
|
830
|
+
dot parachain 1000 --output json
|
|
831
|
+
```
|
|
832
|
+
|
|
833
|
+
Run `dot parachain` with no arguments to see usage and examples.
|
|
834
|
+
|
|
778
835
|
### Getting help
|
|
779
836
|
|
|
780
837
|
Every command supports `--help` to show its detailed usage, available actions, and examples:
|
package/dist/cli.mjs
CHANGED
|
@@ -966,6 +966,7 @@ function parseValue(arg) {
|
|
|
966
966
|
// src/commands/tx.ts
|
|
967
967
|
import { getViewBuilder } from "@polkadot-api/view-builder";
|
|
968
968
|
import { Binary as Binary2 } from "polkadot-api";
|
|
969
|
+
import { stringify as stringifyYaml } from "yaml";
|
|
969
970
|
async function parseStructArgs(meta, fields, args, callLabel) {
|
|
970
971
|
const fieldNames = Object.keys(fields);
|
|
971
972
|
if (args.length !== fieldNames.length) {
|
|
@@ -1967,6 +1968,12 @@ async function generateCompletions(currentWord, precedingWords) {
|
|
|
1967
1968
|
if (firstArg === "hash") {
|
|
1968
1969
|
return filterPrefix(getAlgorithmNames(), currentWord);
|
|
1969
1970
|
}
|
|
1971
|
+
if (firstArg === "parachain") {
|
|
1972
|
+
if (prevWord === "--type") {
|
|
1973
|
+
return filterPrefix(["child", "sibling"], currentWord);
|
|
1974
|
+
}
|
|
1975
|
+
return [];
|
|
1976
|
+
}
|
|
1970
1977
|
return completeDotpath(currentWord, config, knownChains, precedingWords);
|
|
1971
1978
|
}
|
|
1972
1979
|
function detectCategory(words, _knownChains) {
|
|
@@ -2130,7 +2137,7 @@ var init_complete = __esm(() => {
|
|
|
2130
2137
|
apis: "apis",
|
|
2131
2138
|
api: "apis"
|
|
2132
2139
|
};
|
|
2133
|
-
NAMED_COMMANDS = ["chain", "account", "inspect", "hash", "completions"];
|
|
2140
|
+
NAMED_COMMANDS = ["chain", "account", "inspect", "hash", "parachain", "completions"];
|
|
2134
2141
|
CHAIN_SUBCOMMANDS = ["add", "remove", "update", "list", "default"];
|
|
2135
2142
|
ACCOUNT_SUBCOMMANDS = [
|
|
2136
2143
|
"add",
|
|
@@ -2151,7 +2158,7 @@ var init_complete = __esm(() => {
|
|
|
2151
2158
|
// src/cli.ts
|
|
2152
2159
|
import cac from "cac";
|
|
2153
2160
|
// package.json
|
|
2154
|
-
var version = "1.
|
|
2161
|
+
var version = "1.8.1";
|
|
2155
2162
|
|
|
2156
2163
|
// src/commands/account.ts
|
|
2157
2164
|
init_accounts_store();
|
|
@@ -3433,6 +3440,7 @@ async function showItemHelp2(category, target, opts) {
|
|
|
3433
3440
|
init_hash();
|
|
3434
3441
|
init_output();
|
|
3435
3442
|
init_errors();
|
|
3443
|
+
import { readFile as readFile3 } from "node:fs/promises";
|
|
3436
3444
|
async function resolveInput(data, opts) {
|
|
3437
3445
|
const sources = [data !== undefined, !!opts.file, !!opts.stdin].filter(Boolean).length;
|
|
3438
3446
|
if (sources > 1) {
|
|
@@ -3442,26 +3450,15 @@ async function resolveInput(data, opts) {
|
|
|
3442
3450
|
throw new CliError("No input provided. Pass data as argument, or use --file or --stdin");
|
|
3443
3451
|
}
|
|
3444
3452
|
if (opts.file) {
|
|
3445
|
-
const buf = await
|
|
3453
|
+
const buf = await readFile3(opts.file);
|
|
3446
3454
|
return new Uint8Array(buf);
|
|
3447
3455
|
}
|
|
3448
3456
|
if (opts.stdin) {
|
|
3449
|
-
const reader = Bun.stdin.stream().getReader();
|
|
3450
3457
|
const chunks = [];
|
|
3451
|
-
|
|
3452
|
-
|
|
3453
|
-
if (done)
|
|
3454
|
-
break;
|
|
3455
|
-
chunks.push(value);
|
|
3456
|
-
}
|
|
3457
|
-
const totalLen = chunks.reduce((sum, c) => sum + c.length, 0);
|
|
3458
|
-
const result = new Uint8Array(totalLen);
|
|
3459
|
-
let offset = 0;
|
|
3460
|
-
for (const chunk of chunks) {
|
|
3461
|
-
result.set(chunk, offset);
|
|
3462
|
-
offset += chunk.length;
|
|
3458
|
+
for await (const chunk of process.stdin) {
|
|
3459
|
+
chunks.push(chunk);
|
|
3463
3460
|
}
|
|
3464
|
-
return
|
|
3461
|
+
return new Uint8Array(Buffer.concat(chunks));
|
|
3465
3462
|
}
|
|
3466
3463
|
return parseInputData(data);
|
|
3467
3464
|
}
|
|
@@ -3765,6 +3762,97 @@ function registerInspectCommand(cli) {
|
|
|
3765
3762
|
});
|
|
3766
3763
|
}
|
|
3767
3764
|
|
|
3765
|
+
// src/commands/parachain.ts
|
|
3766
|
+
init_accounts();
|
|
3767
|
+
init_output();
|
|
3768
|
+
|
|
3769
|
+
// src/core/parachain.ts
|
|
3770
|
+
var SOVEREIGN_ACCOUNT_TYPES = ["child", "sibling"];
|
|
3771
|
+
var PREFIXES = {
|
|
3772
|
+
child: new Uint8Array([112, 97, 114, 97]),
|
|
3773
|
+
sibling: new Uint8Array([115, 105, 98, 108])
|
|
3774
|
+
};
|
|
3775
|
+
function deriveSovereignAccount(paraId, type) {
|
|
3776
|
+
const result = new Uint8Array(32);
|
|
3777
|
+
result.set(PREFIXES[type], 0);
|
|
3778
|
+
new DataView(result.buffer).setUint32(4, paraId, true);
|
|
3779
|
+
return result;
|
|
3780
|
+
}
|
|
3781
|
+
function isValidParaId(value) {
|
|
3782
|
+
return Number.isInteger(value) && value >= 0 && value <= 4294967295;
|
|
3783
|
+
}
|
|
3784
|
+
|
|
3785
|
+
// src/commands/parachain.ts
|
|
3786
|
+
init_errors();
|
|
3787
|
+
function printParachainHelp() {
|
|
3788
|
+
console.log(`${BOLD}Usage:${RESET} dot parachain <paraId> [options]
|
|
3789
|
+
`);
|
|
3790
|
+
console.log(`${BOLD}Description:${RESET}`);
|
|
3791
|
+
console.log(` Derive sovereign account addresses for a parachain.
|
|
3792
|
+
`);
|
|
3793
|
+
console.log(` ${DIM}Child accounts represent a parachain on the relay chain.${RESET}`);
|
|
3794
|
+
console.log(` ${DIM}Sibling accounts represent a parachain on another parachain.${RESET}
|
|
3795
|
+
`);
|
|
3796
|
+
console.log(`${BOLD}Options:${RESET}`);
|
|
3797
|
+
console.log(` ${CYAN}--type <child|sibling>${RESET} ${DIM}Account type (default: both)${RESET}`);
|
|
3798
|
+
console.log(` ${CYAN}--prefix <N>${RESET} ${DIM}SS58 prefix (default: 42)${RESET}`);
|
|
3799
|
+
console.log(` ${CYAN}--output json${RESET} ${DIM}Output as JSON${RESET}`);
|
|
3800
|
+
console.log(`
|
|
3801
|
+
${BOLD}Examples:${RESET}`);
|
|
3802
|
+
console.log(` ${DIM}$ dot parachain 1000${RESET}`);
|
|
3803
|
+
console.log(` ${DIM}$ dot parachain 2004 --prefix 0${RESET}`);
|
|
3804
|
+
console.log(` ${DIM}$ dot parachain 1000 --type sibling${RESET}`);
|
|
3805
|
+
console.log(` ${DIM}$ dot parachain 2000 --output json${RESET}`);
|
|
3806
|
+
}
|
|
3807
|
+
function validateType(type) {
|
|
3808
|
+
const lower = type.toLowerCase();
|
|
3809
|
+
if (lower === "child" || lower === "sibling")
|
|
3810
|
+
return lower;
|
|
3811
|
+
throw new CliError(`Unknown account type "${type}". Valid types: child, sibling.`);
|
|
3812
|
+
}
|
|
3813
|
+
function registerParachainCommand(cli) {
|
|
3814
|
+
cli.command("parachain [paraId]", "Derive parachain sovereign accounts").option("--type <type>", "Account type: child, sibling (default: both)").option("--prefix <number>", "SS58 prefix for address encoding (default: 42)").action(async (paraIdStr, opts) => {
|
|
3815
|
+
if (!paraIdStr) {
|
|
3816
|
+
printParachainHelp();
|
|
3817
|
+
return;
|
|
3818
|
+
}
|
|
3819
|
+
const paraId = Number(paraIdStr);
|
|
3820
|
+
if (!isValidParaId(paraId)) {
|
|
3821
|
+
throw new CliError(`Invalid parachain ID "${paraIdStr}". Must be a non-negative integer (0 to 4294967295).`);
|
|
3822
|
+
}
|
|
3823
|
+
const prefix = opts.prefix != null ? Number(opts.prefix) : 42;
|
|
3824
|
+
if (Number.isNaN(prefix) || prefix < 0) {
|
|
3825
|
+
throw new CliError(`Invalid prefix "${opts.prefix}". Must be a non-negative integer.`);
|
|
3826
|
+
}
|
|
3827
|
+
const types = opts.type ? [validateType(opts.type)] : SOVEREIGN_ACCOUNT_TYPES;
|
|
3828
|
+
const format = opts.output ?? "pretty";
|
|
3829
|
+
if (format === "json") {
|
|
3830
|
+
const result = { paraId, prefix };
|
|
3831
|
+
for (const type of types) {
|
|
3832
|
+
const accountId = deriveSovereignAccount(paraId, type);
|
|
3833
|
+
result[type] = {
|
|
3834
|
+
publicKey: publicKeyToHex(accountId),
|
|
3835
|
+
ss58: toSs58(accountId, prefix)
|
|
3836
|
+
};
|
|
3837
|
+
}
|
|
3838
|
+
console.log(formatJson(result));
|
|
3839
|
+
} else {
|
|
3840
|
+
printHeading(`Parachain ${paraId} — Sovereign Accounts`);
|
|
3841
|
+
for (const type of types) {
|
|
3842
|
+
const accountId = deriveSovereignAccount(paraId, type);
|
|
3843
|
+
const hex = publicKeyToHex(accountId);
|
|
3844
|
+
const ss58 = toSs58(accountId, prefix);
|
|
3845
|
+
const label = type.charAt(0).toUpperCase() + type.slice(1);
|
|
3846
|
+
console.log(` ${BOLD}${label}:${RESET}`);
|
|
3847
|
+
console.log(` ${BOLD}Public Key:${RESET} ${hex}`);
|
|
3848
|
+
console.log(` ${BOLD}SS58:${RESET} ${ss58}`);
|
|
3849
|
+
console.log(` ${BOLD}Prefix:${RESET} ${prefix}`);
|
|
3850
|
+
console.log();
|
|
3851
|
+
}
|
|
3852
|
+
}
|
|
3853
|
+
});
|
|
3854
|
+
}
|
|
3855
|
+
|
|
3768
3856
|
// src/commands/query.ts
|
|
3769
3857
|
init_store();
|
|
3770
3858
|
init_client();
|
|
@@ -3918,6 +4006,7 @@ init_errors();
|
|
|
3918
4006
|
init_focused_inspect();
|
|
3919
4007
|
import { getViewBuilder as getViewBuilder2 } from "@polkadot-api/view-builder";
|
|
3920
4008
|
import { Binary as Binary3 } from "polkadot-api";
|
|
4009
|
+
import { stringify as stringifyYaml2 } from "yaml";
|
|
3921
4010
|
function parseWaitLevel(raw) {
|
|
3922
4011
|
switch (raw) {
|
|
3923
4012
|
case "broadcast":
|
|
@@ -3968,7 +4057,7 @@ async function handleTx(target, args, opts) {
|
|
|
3968
4057
|
console.log();
|
|
3969
4058
|
return;
|
|
3970
4059
|
}
|
|
3971
|
-
if (!opts.from && !opts.encode) {
|
|
4060
|
+
if (!opts.from && !opts.encode && !opts.yaml && !opts.json) {
|
|
3972
4061
|
if (isRawCall) {
|
|
3973
4062
|
throw new Error("--from is required (or use --encode to output hex without signing)");
|
|
3974
4063
|
}
|
|
@@ -3981,6 +4070,15 @@ async function handleTx(target, args, opts) {
|
|
|
3981
4070
|
if (opts.encode && isRawCall) {
|
|
3982
4071
|
throw new Error("--encode cannot be used with raw call hex (already encoded)");
|
|
3983
4072
|
}
|
|
4073
|
+
if ((opts.yaml || opts.json) && opts.encode) {
|
|
4074
|
+
throw new Error("--yaml/--json and --encode are mutually exclusive");
|
|
4075
|
+
}
|
|
4076
|
+
if ((opts.yaml || opts.json) && opts.dryRun) {
|
|
4077
|
+
throw new Error("--yaml/--json and --dry-run are mutually exclusive");
|
|
4078
|
+
}
|
|
4079
|
+
if (opts.yaml && opts.json) {
|
|
4080
|
+
throw new Error("--yaml and --json are mutually exclusive");
|
|
4081
|
+
}
|
|
3984
4082
|
const config = await loadConfig();
|
|
3985
4083
|
const effectiveChain = opts.chain;
|
|
3986
4084
|
let pallet;
|
|
@@ -3991,9 +4089,10 @@ async function handleTx(target, args, opts) {
|
|
|
3991
4089
|
callName = target.slice(dotIdx + 1);
|
|
3992
4090
|
}
|
|
3993
4091
|
const { name: chainName, chain: chainConfig } = resolveChain(config, effectiveChain);
|
|
3994
|
-
const
|
|
4092
|
+
const decodeOnly = opts.encode || opts.yaml || opts.json;
|
|
4093
|
+
const signer = decodeOnly ? undefined : await resolveAccountSigner(opts.from);
|
|
3995
4094
|
let clientHandle;
|
|
3996
|
-
if (!
|
|
4095
|
+
if (!decodeOnly) {
|
|
3997
4096
|
clientHandle = await createChainClient(chainName, chainConfig, opts.rpc);
|
|
3998
4097
|
}
|
|
3999
4098
|
try {
|
|
@@ -4010,7 +4109,7 @@ async function handleTx(target, args, opts) {
|
|
|
4010
4109
|
}
|
|
4011
4110
|
let unsafeApi;
|
|
4012
4111
|
let txOptions;
|
|
4013
|
-
if (!
|
|
4112
|
+
if (!decodeOnly) {
|
|
4014
4113
|
const userExtOverrides = parseExtOption(opts.ext);
|
|
4015
4114
|
const customSignedExtensions = buildCustomSignedExtensions(meta, userExtOverrides);
|
|
4016
4115
|
txOptions = Object.keys(customSignedExtensions).length > 0 ? { customSignedExtensions } : undefined;
|
|
@@ -4023,9 +4122,14 @@ async function handleTx(target, args, opts) {
|
|
|
4023
4122
|
throw new Error(`Extra arguments are not allowed when submitting a raw call hex.
|
|
4024
4123
|
` + "Usage: dot tx 0x<call_hex> --from <account>");
|
|
4025
4124
|
}
|
|
4125
|
+
callHex = target;
|
|
4126
|
+
if (opts.yaml || opts.json) {
|
|
4127
|
+
const fileObj = decodeCallToFileFormat(meta, callHex, chainName);
|
|
4128
|
+
outputFileFormat(fileObj, !!opts.yaml);
|
|
4129
|
+
return;
|
|
4130
|
+
}
|
|
4026
4131
|
const callBinary = Binary3.fromHex(target);
|
|
4027
4132
|
tx = await unsafeApi.txFromCallData(callBinary);
|
|
4028
|
-
callHex = target;
|
|
4029
4133
|
} else {
|
|
4030
4134
|
const palletNames = getPalletNames(meta);
|
|
4031
4135
|
const palletInfo = findPallet(meta, pallet);
|
|
@@ -4039,11 +4143,17 @@ async function handleTx(target, args, opts) {
|
|
|
4039
4143
|
}
|
|
4040
4144
|
const effectiveArgs = opts.parsedArgs !== undefined ? fileArgsToStrings(opts.parsedArgs) : args;
|
|
4041
4145
|
const callData = await parseCallArgs(meta, palletInfo.name, callInfo.name, effectiveArgs);
|
|
4042
|
-
if (opts.encode) {
|
|
4146
|
+
if (opts.encode || opts.yaml || opts.json) {
|
|
4043
4147
|
const { codec, location } = meta.builder.buildCall(palletInfo.name, callInfo.name);
|
|
4044
4148
|
const encodedArgs = codec.enc(callData);
|
|
4045
4149
|
const fullCall = new Uint8Array([location[0], location[1], ...encodedArgs]);
|
|
4046
|
-
|
|
4150
|
+
const hex = Binary3.fromBytes(fullCall).asHex();
|
|
4151
|
+
if (opts.encode) {
|
|
4152
|
+
console.log(hex);
|
|
4153
|
+
return;
|
|
4154
|
+
}
|
|
4155
|
+
const fileObj = decodeCallToFileFormat(meta, hex, chainName);
|
|
4156
|
+
outputFileFormat(fileObj, !!opts.yaml);
|
|
4047
4157
|
return;
|
|
4048
4158
|
}
|
|
4049
4159
|
tx = unsafeApi.tx[palletInfo.name][callInfo.name](callData);
|
|
@@ -4164,6 +4274,58 @@ function decodeCallFallback(meta, callHex) {
|
|
|
4164
4274
|
const argsStr = formatRawDecoded(args);
|
|
4165
4275
|
return `${palletName2}.${callName} ${argsStr}`;
|
|
4166
4276
|
}
|
|
4277
|
+
function decodeCallToFileFormat(meta, callHex, chainName) {
|
|
4278
|
+
const callTypeId = meta.lookup.call;
|
|
4279
|
+
if (callTypeId == null)
|
|
4280
|
+
throw new Error("No RuntimeCall type ID in metadata");
|
|
4281
|
+
const codec = meta.builder.buildDefinition(callTypeId);
|
|
4282
|
+
const decoded = codec.dec(Binary3.fromHex(callHex).asBytes());
|
|
4283
|
+
const palletName2 = decoded.type;
|
|
4284
|
+
const call = decoded.value;
|
|
4285
|
+
const callName = call.type;
|
|
4286
|
+
const args = call.value;
|
|
4287
|
+
return {
|
|
4288
|
+
chain: chainName,
|
|
4289
|
+
tx: {
|
|
4290
|
+
[palletName2]: {
|
|
4291
|
+
[callName]: sanitizeForSerialization(args) ?? null
|
|
4292
|
+
}
|
|
4293
|
+
}
|
|
4294
|
+
};
|
|
4295
|
+
}
|
|
4296
|
+
function sanitizeForSerialization(value) {
|
|
4297
|
+
if (value === undefined || value === null)
|
|
4298
|
+
return null;
|
|
4299
|
+
if (value instanceof Binary3)
|
|
4300
|
+
return value.asHex();
|
|
4301
|
+
if (typeof value === "bigint") {
|
|
4302
|
+
if (value >= Number.MIN_SAFE_INTEGER && value <= Number.MAX_SAFE_INTEGER) {
|
|
4303
|
+
return Number(value);
|
|
4304
|
+
}
|
|
4305
|
+
return value.toString();
|
|
4306
|
+
}
|
|
4307
|
+
if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
|
|
4308
|
+
return value;
|
|
4309
|
+
}
|
|
4310
|
+
if (Array.isArray(value)) {
|
|
4311
|
+
return value.map(sanitizeForSerialization);
|
|
4312
|
+
}
|
|
4313
|
+
if (typeof value === "object") {
|
|
4314
|
+
const result = {};
|
|
4315
|
+
for (const [k, v] of Object.entries(value)) {
|
|
4316
|
+
result[k] = sanitizeForSerialization(v);
|
|
4317
|
+
}
|
|
4318
|
+
return result;
|
|
4319
|
+
}
|
|
4320
|
+
return String(value);
|
|
4321
|
+
}
|
|
4322
|
+
function outputFileFormat(obj, asYaml) {
|
|
4323
|
+
if (asYaml) {
|
|
4324
|
+
process.stdout.write(stringifyYaml2(obj));
|
|
4325
|
+
} else {
|
|
4326
|
+
console.log(JSON.stringify(obj, null, 2));
|
|
4327
|
+
}
|
|
4328
|
+
}
|
|
4167
4329
|
function formatRawDecoded(value) {
|
|
4168
4330
|
if (value === undefined || value === null)
|
|
4169
4331
|
return "null";
|
|
@@ -4786,7 +4948,7 @@ function watchTransaction(observable, level) {
|
|
|
4786
4948
|
|
|
4787
4949
|
// src/config/store.ts
|
|
4788
4950
|
init_types();
|
|
4789
|
-
import { access as access3, mkdir as mkdir3, readFile as
|
|
4951
|
+
import { access as access3, mkdir as mkdir3, readFile as readFile4, rm as rm2, writeFile as writeFile3 } from "node:fs/promises";
|
|
4790
4952
|
import { homedir as homedir2 } from "node:os";
|
|
4791
4953
|
import { join as join3 } from "node:path";
|
|
4792
4954
|
var DOT_DIR2 = join3(homedir2(), ".polkadot");
|
|
@@ -4806,7 +4968,7 @@ async function fileExists3(path) {
|
|
|
4806
4968
|
async function loadConfig2() {
|
|
4807
4969
|
await ensureDir3(DOT_DIR2);
|
|
4808
4970
|
if (await fileExists3(CONFIG_PATH2)) {
|
|
4809
|
-
const saved = JSON.parse(await
|
|
4971
|
+
const saved = JSON.parse(await readFile4(CONFIG_PATH2, "utf-8"));
|
|
4810
4972
|
return {
|
|
4811
4973
|
...saved,
|
|
4812
4974
|
chains: { ...DEFAULT_CONFIG.chains, ...saved.chains }
|
|
@@ -4823,6 +4985,7 @@ async function saveConfig2(config) {
|
|
|
4823
4985
|
|
|
4824
4986
|
// src/core/file-loader.ts
|
|
4825
4987
|
init_errors();
|
|
4988
|
+
import { access as access4, readFile as readFile5 } from "node:fs/promises";
|
|
4826
4989
|
import { parse as parseYaml } from "yaml";
|
|
4827
4990
|
var CATEGORIES = ["tx", "query", "const", "apis"];
|
|
4828
4991
|
var FILE_EXTENSIONS = [".json", ".yaml", ".yml"];
|
|
@@ -4870,16 +5033,24 @@ function substituteVars(text, vars) {
|
|
|
4870
5033
|
return envVal;
|
|
4871
5034
|
if (defaultValue !== undefined)
|
|
4872
5035
|
return defaultValue;
|
|
4873
|
-
throw new CliError(`Undefined variable "\${${varName}}" in file.
|
|
5036
|
+
throw new CliError(`Undefined variable "\${${varName}}" in file.
|
|
5037
|
+
|
|
5038
|
+
` + ` Provide it using one of:
|
|
5039
|
+
` + ` --var ${varName}=VALUE
|
|
5040
|
+
` + ` ${varName}=VALUE dot ... (environment variable)
|
|
5041
|
+
` + ` \${${varName}:-default} (inline default in file)`);
|
|
4874
5042
|
});
|
|
4875
5043
|
}
|
|
5044
|
+
function quoteYamlHexValues(text) {
|
|
5045
|
+
return text.replace(/^(\s*(?:[^:]+:\s+|-\s+))(0x[0-9a-fA-F]+)\s*$/gm, '$1"$2"');
|
|
5046
|
+
}
|
|
4876
5047
|
async function loadCommandFile(filePath, cliVars) {
|
|
4877
|
-
|
|
4878
|
-
|
|
4879
|
-
|
|
5048
|
+
try {
|
|
5049
|
+
await access4(filePath);
|
|
5050
|
+
} catch {
|
|
4880
5051
|
throw new CliError(`File not found: ${filePath}`);
|
|
4881
5052
|
}
|
|
4882
|
-
const rawText = await
|
|
5053
|
+
const rawText = await readFile5(filePath, "utf-8");
|
|
4883
5054
|
if (!rawText.trim()) {
|
|
4884
5055
|
throw new CliError(`File is empty: ${filePath}`);
|
|
4885
5056
|
}
|
|
@@ -4898,9 +5069,10 @@ async function loadCommandFile(filePath, cliVars) {
|
|
|
4898
5069
|
} catch {}
|
|
4899
5070
|
const mergedVars = { ...fileVars, ...cliVars };
|
|
4900
5071
|
const substituted = substituteVars(rawText, mergedVars);
|
|
5072
|
+
const textToParse = isJson ? substituted : quoteYamlHexValues(substituted);
|
|
4901
5073
|
let parsed;
|
|
4902
5074
|
try {
|
|
4903
|
-
parsed = isJson ? JSON.parse(
|
|
5075
|
+
parsed = isJson ? JSON.parse(textToParse) : parseYaml(textToParse);
|
|
4904
5076
|
} catch (err) {
|
|
4905
5077
|
const format = isJson ? "JSON" : "YAML";
|
|
4906
5078
|
const msg = err instanceof Error ? err.message : String(err);
|
|
@@ -5191,12 +5363,15 @@ if (process.argv[2] === "__complete") {
|
|
|
5191
5363
|
console.log(" dot apis.Core.version Call a runtime API");
|
|
5192
5364
|
console.log(" dot polkadot.query.System.Number With chain prefix");
|
|
5193
5365
|
console.log(" dot ./transfer.yaml --from alice Run from file");
|
|
5366
|
+
console.log(" dot tx.0x1f0003... --yaml Decode hex call to YAML");
|
|
5367
|
+
console.log(" dot tx.System.remark 0xdead --json Encode & output as JSON file format");
|
|
5194
5368
|
console.log();
|
|
5195
5369
|
console.log("Commands:");
|
|
5196
5370
|
console.log(" inspect [target] Inspect chain metadata (alias: explore)");
|
|
5197
5371
|
console.log(" chain Manage chain configurations");
|
|
5198
5372
|
console.log(" account Manage accounts");
|
|
5199
5373
|
console.log(" hash Hash utilities");
|
|
5374
|
+
console.log(" parachain Derive parachain sovereign accounts");
|
|
5200
5375
|
console.log(" completions <sh> Generate shell completions (zsh, bash, fish)");
|
|
5201
5376
|
console.log();
|
|
5202
5377
|
console.log("Global options:");
|
|
@@ -5219,8 +5394,9 @@ if (process.argv[2] === "__complete") {
|
|
|
5219
5394
|
registerInspectCommand(cli);
|
|
5220
5395
|
registerAccountCommands(cli);
|
|
5221
5396
|
registerHashCommand(cli);
|
|
5397
|
+
registerParachainCommand(cli);
|
|
5222
5398
|
registerCompletionsCommand(cli);
|
|
5223
|
-
cli.command("[dotpath] [...args]").option("--from <name>", "Account to sign with (for tx)").option("--dry-run", "Estimate fees without submitting (for tx)").option("--encode", "Encode call to hex without signing (for tx)").option("--ext <json>", "Custom signed extension values as JSON (for tx)").option("-w, --wait <level>", "Resolve at: broadcast, best-block (or best), finalized (for tx)", {
|
|
5399
|
+
cli.command("[dotpath] [...args]").option("--from <name>", "Account to sign with (for tx)").option("--dry-run", "Estimate fees without submitting (for tx)").option("--encode", "Encode call to hex without signing (for tx)").option("--yaml", "Decode call to YAML file format (for tx)").option("--json", "Decode call to JSON file format (for tx)").option("--ext <json>", "Custom signed extension values as JSON (for tx)").option("-w, --wait <level>", "Resolve at: broadcast, best-block (or best), finalized (for tx)", {
|
|
5224
5400
|
default: "finalized"
|
|
5225
5401
|
}).option("--limit <n>", "Max entries to return for map queries (0 = unlimited)", {
|
|
5226
5402
|
default: 100
|
|
@@ -5242,6 +5418,8 @@ if (process.argv[2] === "__complete") {
|
|
|
5242
5418
|
from: opts.from,
|
|
5243
5419
|
dryRun: opts.dryRun,
|
|
5244
5420
|
encode: opts.encode,
|
|
5421
|
+
yaml: opts.yaml,
|
|
5422
|
+
json: opts.json,
|
|
5245
5423
|
ext: opts.ext,
|
|
5246
5424
|
wait: opts.wait,
|
|
5247
5425
|
parsedArgs: cmd.args
|
|
@@ -5302,6 +5480,8 @@ if (process.argv[2] === "__complete") {
|
|
|
5302
5480
|
from: opts.from,
|
|
5303
5481
|
dryRun: opts.dryRun,
|
|
5304
5482
|
encode: opts.encode,
|
|
5483
|
+
yaml: opts.yaml,
|
|
5484
|
+
json: opts.json,
|
|
5305
5485
|
ext: opts.ext,
|
|
5306
5486
|
wait: opts.wait
|
|
5307
5487
|
});
|
|
@@ -5311,6 +5491,8 @@ if (process.argv[2] === "__complete") {
|
|
|
5311
5491
|
from: opts.from,
|
|
5312
5492
|
dryRun: opts.dryRun,
|
|
5313
5493
|
encode: opts.encode,
|
|
5494
|
+
yaml: opts.yaml,
|
|
5495
|
+
json: opts.json,
|
|
5314
5496
|
ext: opts.ext,
|
|
5315
5497
|
wait: opts.wait
|
|
5316
5498
|
});
|