polkadot-cli 1.17.0 → 1.18.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 +196 -38
- package/dist/cli.mjs +1214 -89
- package/package.json +2 -1
package/dist/cli.mjs
CHANGED
|
@@ -240,6 +240,9 @@ function getMetadataPath(chainName) {
|
|
|
240
240
|
function getMetadataFingerprintPath(chainName) {
|
|
241
241
|
return join(getChainDir(chainName), "metadata.fingerprint.json");
|
|
242
242
|
}
|
|
243
|
+
function getRpcMethodsPath(chainName) {
|
|
244
|
+
return join(getChainDir(chainName), "rpc-methods.json");
|
|
245
|
+
}
|
|
243
246
|
function getConfigPath() {
|
|
244
247
|
return join(getConfigDir(), "config.json");
|
|
245
248
|
}
|
|
@@ -305,6 +308,31 @@ async function loadMetadataFingerprint(chainName) {
|
|
|
305
308
|
return null;
|
|
306
309
|
}
|
|
307
310
|
}
|
|
311
|
+
async function loadRpcMethods(chainName) {
|
|
312
|
+
const path = getRpcMethodsPath(chainName);
|
|
313
|
+
if (!await fileExists(path))
|
|
314
|
+
return null;
|
|
315
|
+
try {
|
|
316
|
+
const parsed = JSON.parse(await readFile(path, "utf-8"));
|
|
317
|
+
if (parsed && Array.isArray(parsed.methods) && typeof parsed.version === "number" && typeof parsed.fetchedAt === "string") {
|
|
318
|
+
return parsed;
|
|
319
|
+
}
|
|
320
|
+
return null;
|
|
321
|
+
} catch {
|
|
322
|
+
return null;
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
async function saveRpcMethods(chainName, methods, version2) {
|
|
326
|
+
const dir = getChainDir(chainName);
|
|
327
|
+
await ensureDir(dir);
|
|
328
|
+
const cache = {
|
|
329
|
+
methods,
|
|
330
|
+
version: version2,
|
|
331
|
+
fetchedAt: new Date().toISOString()
|
|
332
|
+
};
|
|
333
|
+
await writeFile(getRpcMethodsPath(chainName), `${JSON.stringify(cache, null, 2)}
|
|
334
|
+
`);
|
|
335
|
+
}
|
|
308
336
|
async function removeChainData(chainName) {
|
|
309
337
|
const dir = getChainDir(chainName);
|
|
310
338
|
await rm(dir, { recursive: true, force: true });
|
|
@@ -375,6 +403,15 @@ function isEnvSecret(secret) {
|
|
|
375
403
|
function isWatchOnly(account) {
|
|
376
404
|
return account.secret === undefined;
|
|
377
405
|
}
|
|
406
|
+
function classifyAccount(account) {
|
|
407
|
+
if (account.source?.kind === "pallet")
|
|
408
|
+
return "pallet";
|
|
409
|
+
if (account.source?.kind === "parachain")
|
|
410
|
+
return "parachain";
|
|
411
|
+
if (account.secret !== undefined)
|
|
412
|
+
return "signer";
|
|
413
|
+
return "watch-only";
|
|
414
|
+
}
|
|
378
415
|
|
|
379
416
|
// src/utils/fuzzy-match.ts
|
|
380
417
|
function levenshtein(a, b) {
|
|
@@ -2559,6 +2596,477 @@ var init_focused_inspect = __esm(() => {
|
|
|
2559
2596
|
init_pretty_type();
|
|
2560
2597
|
});
|
|
2561
2598
|
|
|
2599
|
+
// src/data/rpc-registry.ts
|
|
2600
|
+
function inferFamily(method) {
|
|
2601
|
+
const prefix = method.split("_")[0];
|
|
2602
|
+
switch (prefix) {
|
|
2603
|
+
case "system":
|
|
2604
|
+
case "chain":
|
|
2605
|
+
case "state":
|
|
2606
|
+
case "author":
|
|
2607
|
+
case "payment":
|
|
2608
|
+
case "babe":
|
|
2609
|
+
case "grandpa":
|
|
2610
|
+
case "beefy":
|
|
2611
|
+
case "mmr":
|
|
2612
|
+
case "offchain":
|
|
2613
|
+
case "dev":
|
|
2614
|
+
return prefix;
|
|
2615
|
+
case "rpc":
|
|
2616
|
+
return "spec";
|
|
2617
|
+
case "chainHead":
|
|
2618
|
+
return "chainHead";
|
|
2619
|
+
case "chainSpec":
|
|
2620
|
+
return "chainSpec";
|
|
2621
|
+
case "transaction":
|
|
2622
|
+
return "transaction";
|
|
2623
|
+
case "archive":
|
|
2624
|
+
return "archive";
|
|
2625
|
+
default:
|
|
2626
|
+
return "other";
|
|
2627
|
+
}
|
|
2628
|
+
}
|
|
2629
|
+
var RPC_REGISTRY;
|
|
2630
|
+
var init_rpc_registry = __esm(() => {
|
|
2631
|
+
RPC_REGISTRY = {
|
|
2632
|
+
system_health: {
|
|
2633
|
+
description: "Node sync state (peers, isSyncing, shouldHavePeers).",
|
|
2634
|
+
family: "system",
|
|
2635
|
+
args: []
|
|
2636
|
+
},
|
|
2637
|
+
system_syncState: {
|
|
2638
|
+
description: "Block-level sync progress (startingBlock, currentBlock, highestBlock).",
|
|
2639
|
+
family: "system",
|
|
2640
|
+
args: []
|
|
2641
|
+
},
|
|
2642
|
+
system_version: {
|
|
2643
|
+
description: "Node software version string.",
|
|
2644
|
+
family: "system",
|
|
2645
|
+
args: []
|
|
2646
|
+
},
|
|
2647
|
+
system_name: {
|
|
2648
|
+
description: "Node implementation name.",
|
|
2649
|
+
family: "system",
|
|
2650
|
+
args: []
|
|
2651
|
+
},
|
|
2652
|
+
system_chain: {
|
|
2653
|
+
description: "Chain name as reported by the node.",
|
|
2654
|
+
family: "system",
|
|
2655
|
+
args: []
|
|
2656
|
+
},
|
|
2657
|
+
system_chainType: {
|
|
2658
|
+
description: "Chain type (Live, Development, Local).",
|
|
2659
|
+
family: "system",
|
|
2660
|
+
args: []
|
|
2661
|
+
},
|
|
2662
|
+
system_properties: {
|
|
2663
|
+
description: "Chain properties (ss58Format, tokenDecimals, tokenSymbol).",
|
|
2664
|
+
family: "system",
|
|
2665
|
+
args: []
|
|
2666
|
+
},
|
|
2667
|
+
system_peers: {
|
|
2668
|
+
description: "Connected peer details (peerId, roles, bestHash, bestNumber).",
|
|
2669
|
+
family: "system",
|
|
2670
|
+
args: []
|
|
2671
|
+
},
|
|
2672
|
+
system_localPeerId: {
|
|
2673
|
+
description: "Base58 PeerId of this node.",
|
|
2674
|
+
family: "system",
|
|
2675
|
+
args: []
|
|
2676
|
+
},
|
|
2677
|
+
system_localListenAddresses: {
|
|
2678
|
+
description: "Multiaddrs this node listens on.",
|
|
2679
|
+
family: "system",
|
|
2680
|
+
args: []
|
|
2681
|
+
},
|
|
2682
|
+
system_nodeRoles: {
|
|
2683
|
+
description: "Role(s) of the node (Authority, Full, Light, …).",
|
|
2684
|
+
family: "system",
|
|
2685
|
+
args: []
|
|
2686
|
+
},
|
|
2687
|
+
system_addLogFilter: {
|
|
2688
|
+
description: "Add a tracing/log filter directive at runtime.",
|
|
2689
|
+
family: "system",
|
|
2690
|
+
args: [{ name: "directives", type: "string" }],
|
|
2691
|
+
dangerous: true
|
|
2692
|
+
},
|
|
2693
|
+
system_resetLogFilter: {
|
|
2694
|
+
description: "Reset log filter to the default set at startup.",
|
|
2695
|
+
family: "system",
|
|
2696
|
+
args: [],
|
|
2697
|
+
dangerous: true
|
|
2698
|
+
},
|
|
2699
|
+
system_accountNextIndex: {
|
|
2700
|
+
description: "Next nonce for an account, including pending mempool extrinsics.",
|
|
2701
|
+
family: "system",
|
|
2702
|
+
args: [{ name: "address", type: "AccountId" }]
|
|
2703
|
+
},
|
|
2704
|
+
system_dryRun: {
|
|
2705
|
+
description: "Dry-run an extrinsic, returning its ApplyExtrinsicResult.",
|
|
2706
|
+
family: "system",
|
|
2707
|
+
args: [
|
|
2708
|
+
{ name: "extrinsic", type: "hex" },
|
|
2709
|
+
{ name: "at", type: "H256", optional: true }
|
|
2710
|
+
]
|
|
2711
|
+
},
|
|
2712
|
+
chain_getBlock: {
|
|
2713
|
+
description: "Full block (header + extrinsics) by hash.",
|
|
2714
|
+
family: "chain",
|
|
2715
|
+
args: [{ name: "blockHash", type: "H256", optional: true, description: "latest if omitted" }]
|
|
2716
|
+
},
|
|
2717
|
+
chain_getBlockHash: {
|
|
2718
|
+
description: "Block hash by number, or latest if omitted.",
|
|
2719
|
+
family: "chain",
|
|
2720
|
+
args: [{ name: "blockNumber", type: "u32", optional: true }]
|
|
2721
|
+
},
|
|
2722
|
+
chain_getFinalizedHead: {
|
|
2723
|
+
description: "Hash of the latest finalized head.",
|
|
2724
|
+
family: "chain",
|
|
2725
|
+
args: []
|
|
2726
|
+
},
|
|
2727
|
+
chain_getHeader: {
|
|
2728
|
+
description: "Block header by hash, or latest if omitted.",
|
|
2729
|
+
family: "chain",
|
|
2730
|
+
args: [{ name: "blockHash", type: "H256", optional: true }]
|
|
2731
|
+
},
|
|
2732
|
+
chain_subscribeAllHeads: {
|
|
2733
|
+
description: "Subscribe to all imported headers.",
|
|
2734
|
+
family: "chain",
|
|
2735
|
+
args: [],
|
|
2736
|
+
subscription: true
|
|
2737
|
+
},
|
|
2738
|
+
chain_subscribeFinalizedHeads: {
|
|
2739
|
+
description: "Subscribe to finalized-head changes.",
|
|
2740
|
+
family: "chain",
|
|
2741
|
+
args: [],
|
|
2742
|
+
subscription: true
|
|
2743
|
+
},
|
|
2744
|
+
chain_subscribeNewHeads: {
|
|
2745
|
+
description: "Subscribe to best-block-head changes.",
|
|
2746
|
+
family: "chain",
|
|
2747
|
+
args: [],
|
|
2748
|
+
subscription: true
|
|
2749
|
+
},
|
|
2750
|
+
state_call: {
|
|
2751
|
+
description: "Invoke a runtime API method by name with raw SCALE-encoded arguments.",
|
|
2752
|
+
family: "state",
|
|
2753
|
+
args: [
|
|
2754
|
+
{ name: "method", type: "string", description: "e.g. Core_version" },
|
|
2755
|
+
{ name: "data", type: "hex", description: "SCALE-encoded args (0x for none)" },
|
|
2756
|
+
{ name: "at", type: "H256", optional: true }
|
|
2757
|
+
]
|
|
2758
|
+
},
|
|
2759
|
+
state_getMetadata: {
|
|
2760
|
+
description: "Raw SCALE-encoded runtime metadata at a block.",
|
|
2761
|
+
family: "state",
|
|
2762
|
+
args: [{ name: "at", type: "H256", optional: true }]
|
|
2763
|
+
},
|
|
2764
|
+
state_getRuntimeVersion: {
|
|
2765
|
+
description: "Runtime version at a block.",
|
|
2766
|
+
family: "state",
|
|
2767
|
+
args: [{ name: "at", type: "H256", optional: true }]
|
|
2768
|
+
},
|
|
2769
|
+
state_getStorage: {
|
|
2770
|
+
description: "Raw SCALE-encoded storage value at a key.",
|
|
2771
|
+
family: "state",
|
|
2772
|
+
args: [
|
|
2773
|
+
{ name: "key", type: "StorageKey" },
|
|
2774
|
+
{ name: "at", type: "H256", optional: true }
|
|
2775
|
+
]
|
|
2776
|
+
},
|
|
2777
|
+
state_getStorageHash: {
|
|
2778
|
+
description: "Blake2 hash of the value at a storage key.",
|
|
2779
|
+
family: "state",
|
|
2780
|
+
args: [
|
|
2781
|
+
{ name: "key", type: "StorageKey" },
|
|
2782
|
+
{ name: "at", type: "H256", optional: true }
|
|
2783
|
+
]
|
|
2784
|
+
},
|
|
2785
|
+
state_getStorageSize: {
|
|
2786
|
+
description: "Byte length of the value at a storage key.",
|
|
2787
|
+
family: "state",
|
|
2788
|
+
args: [
|
|
2789
|
+
{ name: "key", type: "StorageKey" },
|
|
2790
|
+
{ name: "at", type: "H256", optional: true }
|
|
2791
|
+
]
|
|
2792
|
+
},
|
|
2793
|
+
state_getKeysPaged: {
|
|
2794
|
+
description: "Paginated key iteration under a prefix.",
|
|
2795
|
+
family: "state",
|
|
2796
|
+
args: [
|
|
2797
|
+
{ name: "prefix", type: "StorageKey" },
|
|
2798
|
+
{ name: "count", type: "u32" },
|
|
2799
|
+
{ name: "startKey", type: "StorageKey", optional: true },
|
|
2800
|
+
{ name: "at", type: "H256", optional: true }
|
|
2801
|
+
]
|
|
2802
|
+
},
|
|
2803
|
+
state_queryStorageAt: {
|
|
2804
|
+
description: "Read multiple keys at a single block.",
|
|
2805
|
+
family: "state",
|
|
2806
|
+
args: [
|
|
2807
|
+
{ name: "keys", type: "StorageKey[]" },
|
|
2808
|
+
{ name: "at", type: "H256", optional: true }
|
|
2809
|
+
]
|
|
2810
|
+
},
|
|
2811
|
+
state_traceBlock: {
|
|
2812
|
+
description: "Per-block storage access trace (heavy: archival/debug nodes only).",
|
|
2813
|
+
family: "state",
|
|
2814
|
+
args: [
|
|
2815
|
+
{ name: "blockHash", type: "H256" },
|
|
2816
|
+
{ name: "targets", type: "string", optional: true },
|
|
2817
|
+
{ name: "storageKeys", type: "string", optional: true },
|
|
2818
|
+
{ name: "methods", type: "string", optional: true }
|
|
2819
|
+
]
|
|
2820
|
+
},
|
|
2821
|
+
state_subscribeRuntimeVersion: {
|
|
2822
|
+
description: "Subscribe to runtime upgrades.",
|
|
2823
|
+
family: "state",
|
|
2824
|
+
args: [],
|
|
2825
|
+
subscription: true
|
|
2826
|
+
},
|
|
2827
|
+
state_subscribeStorage: {
|
|
2828
|
+
description: "Subscribe to changes for a set of keys.",
|
|
2829
|
+
family: "state",
|
|
2830
|
+
args: [{ name: "keys", type: "StorageKey[]" }],
|
|
2831
|
+
subscription: true
|
|
2832
|
+
},
|
|
2833
|
+
author_pendingExtrinsics: {
|
|
2834
|
+
description: "Mempool snapshot — encoded extrinsics waiting to be included.",
|
|
2835
|
+
family: "author",
|
|
2836
|
+
args: []
|
|
2837
|
+
},
|
|
2838
|
+
author_submitExtrinsic: {
|
|
2839
|
+
description: "Submit a signed extrinsic to the mempool. Returns the tx hash.",
|
|
2840
|
+
family: "author",
|
|
2841
|
+
args: [{ name: "extrinsic", type: "hex" }],
|
|
2842
|
+
dangerous: true
|
|
2843
|
+
},
|
|
2844
|
+
author_removeExtrinsic: {
|
|
2845
|
+
description: "Remove specific extrinsics from the mempool by hash.",
|
|
2846
|
+
family: "author",
|
|
2847
|
+
args: [{ name: "bytesOrHash", type: "ExtrinsicOrHash[]" }],
|
|
2848
|
+
dangerous: true
|
|
2849
|
+
},
|
|
2850
|
+
author_hasKey: {
|
|
2851
|
+
description: "Whether the keystore has the public key for a given key type.",
|
|
2852
|
+
family: "author",
|
|
2853
|
+
args: [
|
|
2854
|
+
{ name: "publicKey", type: "hex" },
|
|
2855
|
+
{ name: "keyType", type: "string", description: "e.g. babe, gran, imon" }
|
|
2856
|
+
]
|
|
2857
|
+
},
|
|
2858
|
+
author_hasSessionKeys: {
|
|
2859
|
+
description: "Whether the keystore has all keys for a session-keys blob.",
|
|
2860
|
+
family: "author",
|
|
2861
|
+
args: [{ name: "sessionKeys", type: "hex" }]
|
|
2862
|
+
},
|
|
2863
|
+
author_rotateKeys: {
|
|
2864
|
+
description: "Generate a new set of session keys and return the public-keys blob.",
|
|
2865
|
+
family: "author",
|
|
2866
|
+
args: [],
|
|
2867
|
+
dangerous: true
|
|
2868
|
+
},
|
|
2869
|
+
author_insertKey: {
|
|
2870
|
+
description: "Insert a key into the node keystore.",
|
|
2871
|
+
family: "author",
|
|
2872
|
+
args: [
|
|
2873
|
+
{ name: "keyType", type: "string" },
|
|
2874
|
+
{ name: "suri", type: "string" },
|
|
2875
|
+
{ name: "publicKey", type: "hex" }
|
|
2876
|
+
],
|
|
2877
|
+
dangerous: true
|
|
2878
|
+
},
|
|
2879
|
+
author_submitAndWatchExtrinsic: {
|
|
2880
|
+
description: "Submit an extrinsic and subscribe to its status updates.",
|
|
2881
|
+
family: "author",
|
|
2882
|
+
args: [{ name: "extrinsic", type: "hex" }],
|
|
2883
|
+
dangerous: true,
|
|
2884
|
+
subscription: true
|
|
2885
|
+
},
|
|
2886
|
+
payment_queryInfo: {
|
|
2887
|
+
description: "Pre-submission fee estimate (weight, partialFee, class).",
|
|
2888
|
+
family: "payment",
|
|
2889
|
+
args: [
|
|
2890
|
+
{ name: "extrinsic", type: "hex" },
|
|
2891
|
+
{ name: "at", type: "H256", optional: true }
|
|
2892
|
+
]
|
|
2893
|
+
},
|
|
2894
|
+
payment_queryFeeDetails: {
|
|
2895
|
+
description: "Fee breakdown (baseFee, lenFee, adjustedWeightFee, tip).",
|
|
2896
|
+
family: "payment",
|
|
2897
|
+
args: [
|
|
2898
|
+
{ name: "extrinsic", type: "hex" },
|
|
2899
|
+
{ name: "at", type: "H256", optional: true }
|
|
2900
|
+
]
|
|
2901
|
+
},
|
|
2902
|
+
babe_epochAuthorship: {
|
|
2903
|
+
description: "Slots this node is allowed to author in the current epoch.",
|
|
2904
|
+
family: "babe",
|
|
2905
|
+
args: []
|
|
2906
|
+
},
|
|
2907
|
+
grandpa_proveFinality: {
|
|
2908
|
+
description: "Finality proof up to a block (for light clients).",
|
|
2909
|
+
family: "grandpa",
|
|
2910
|
+
args: [{ name: "blockNumber", type: "u32" }]
|
|
2911
|
+
},
|
|
2912
|
+
grandpa_roundState: {
|
|
2913
|
+
description: "GRANDPA round state (best round, total weight, voters).",
|
|
2914
|
+
family: "grandpa",
|
|
2915
|
+
args: []
|
|
2916
|
+
},
|
|
2917
|
+
grandpa_subscribeJustifications: {
|
|
2918
|
+
description: "Subscribe to GRANDPA justifications.",
|
|
2919
|
+
family: "grandpa",
|
|
2920
|
+
args: [],
|
|
2921
|
+
subscription: true
|
|
2922
|
+
},
|
|
2923
|
+
beefy_getFinalizedHead: {
|
|
2924
|
+
description: "Latest BEEFY-finalized block hash.",
|
|
2925
|
+
family: "beefy",
|
|
2926
|
+
args: []
|
|
2927
|
+
},
|
|
2928
|
+
beefy_subscribeJustifications: {
|
|
2929
|
+
description: "Subscribe to BEEFY signed commitments.",
|
|
2930
|
+
family: "beefy",
|
|
2931
|
+
args: [],
|
|
2932
|
+
subscription: true
|
|
2933
|
+
},
|
|
2934
|
+
mmr_root: {
|
|
2935
|
+
description: "MMR root at a block.",
|
|
2936
|
+
family: "mmr",
|
|
2937
|
+
args: [{ name: "at", type: "H256", optional: true }]
|
|
2938
|
+
},
|
|
2939
|
+
mmr_generateProof: {
|
|
2940
|
+
description: "Generate an MMR proof for given leaf indices.",
|
|
2941
|
+
family: "mmr",
|
|
2942
|
+
args: [
|
|
2943
|
+
{ name: "blockNumbers", type: "u32[]" },
|
|
2944
|
+
{ name: "bestKnownBlockNumber", type: "u32", optional: true },
|
|
2945
|
+
{ name: "at", type: "H256", optional: true }
|
|
2946
|
+
]
|
|
2947
|
+
},
|
|
2948
|
+
mmr_verifyProof: {
|
|
2949
|
+
description: "Verify an MMR proof.",
|
|
2950
|
+
family: "mmr",
|
|
2951
|
+
args: [{ name: "proof", type: "MmrLeavesProof" }]
|
|
2952
|
+
},
|
|
2953
|
+
offchain_localStorageGet: {
|
|
2954
|
+
description: "Read from offchain-worker local storage (PERSISTENT or LOCAL kind).",
|
|
2955
|
+
family: "offchain",
|
|
2956
|
+
args: [
|
|
2957
|
+
{ name: "kind", type: "string", description: "PERSISTENT or LOCAL" },
|
|
2958
|
+
{ name: "key", type: "hex" }
|
|
2959
|
+
]
|
|
2960
|
+
},
|
|
2961
|
+
offchain_localStorageSet: {
|
|
2962
|
+
description: "Write to offchain-worker local storage.",
|
|
2963
|
+
family: "offchain",
|
|
2964
|
+
args: [
|
|
2965
|
+
{ name: "kind", type: "string" },
|
|
2966
|
+
{ name: "key", type: "hex" },
|
|
2967
|
+
{ name: "value", type: "hex" }
|
|
2968
|
+
],
|
|
2969
|
+
dangerous: true
|
|
2970
|
+
},
|
|
2971
|
+
dev_newBlock: {
|
|
2972
|
+
description: "Manually trigger block production (manual-seal dev nodes).",
|
|
2973
|
+
family: "dev",
|
|
2974
|
+
args: [
|
|
2975
|
+
{
|
|
2976
|
+
name: "params",
|
|
2977
|
+
type: "json",
|
|
2978
|
+
optional: true,
|
|
2979
|
+
description: "{ create_empty?: bool, finalize?: bool }"
|
|
2980
|
+
}
|
|
2981
|
+
],
|
|
2982
|
+
dangerous: true
|
|
2983
|
+
},
|
|
2984
|
+
dev_setHead: {
|
|
2985
|
+
description: "Set the chain head to a specific block (manual-seal dev nodes).",
|
|
2986
|
+
family: "dev",
|
|
2987
|
+
args: [{ name: "blockHash", type: "H256" }],
|
|
2988
|
+
dangerous: true
|
|
2989
|
+
},
|
|
2990
|
+
rpc_methods: {
|
|
2991
|
+
description: "List of JSON-RPC methods this node exposes.",
|
|
2992
|
+
family: "spec",
|
|
2993
|
+
args: []
|
|
2994
|
+
},
|
|
2995
|
+
chainSpec_v1_chainName: {
|
|
2996
|
+
description: "Chain name from the chain spec (no SCALE).",
|
|
2997
|
+
family: "chainSpec",
|
|
2998
|
+
args: []
|
|
2999
|
+
},
|
|
3000
|
+
chainSpec_v1_genesisHash: {
|
|
3001
|
+
description: "Genesis block hash.",
|
|
3002
|
+
family: "chainSpec",
|
|
3003
|
+
args: []
|
|
3004
|
+
},
|
|
3005
|
+
chainSpec_v1_properties: {
|
|
3006
|
+
description: "Chain properties from the chain spec.",
|
|
3007
|
+
family: "chainSpec",
|
|
3008
|
+
args: []
|
|
3009
|
+
},
|
|
3010
|
+
archive_v1_finalizedHeight: {
|
|
3011
|
+
description: "Latest finalized block number this archive node has.",
|
|
3012
|
+
family: "archive",
|
|
3013
|
+
args: []
|
|
3014
|
+
},
|
|
3015
|
+
archive_v1_genesisHash: {
|
|
3016
|
+
description: "Genesis block hash from the archive node.",
|
|
3017
|
+
family: "archive",
|
|
3018
|
+
args: []
|
|
3019
|
+
},
|
|
3020
|
+
archive_v1_hashByHeight: {
|
|
3021
|
+
description: "Block hashes at a height (canonical + forks).",
|
|
3022
|
+
family: "archive",
|
|
3023
|
+
args: [{ name: "height", type: "u32" }]
|
|
3024
|
+
},
|
|
3025
|
+
archive_v1_header: {
|
|
3026
|
+
description: "Header for an archived block.",
|
|
3027
|
+
family: "archive",
|
|
3028
|
+
args: [{ name: "blockHash", type: "H256" }]
|
|
3029
|
+
},
|
|
3030
|
+
archive_v1_body: {
|
|
3031
|
+
description: "Block body (extrinsics) for an archived block.",
|
|
3032
|
+
family: "archive",
|
|
3033
|
+
args: [{ name: "blockHash", type: "H256" }]
|
|
3034
|
+
},
|
|
3035
|
+
archive_v1_call: {
|
|
3036
|
+
description: "Invoke a runtime API at an archived block.",
|
|
3037
|
+
family: "archive",
|
|
3038
|
+
args: [
|
|
3039
|
+
{ name: "blockHash", type: "H256" },
|
|
3040
|
+
{ name: "function", type: "string" },
|
|
3041
|
+
{ name: "callParameters", type: "hex" }
|
|
3042
|
+
]
|
|
3043
|
+
},
|
|
3044
|
+
archive_v1_storage: {
|
|
3045
|
+
description: "Read storage at an archived block.",
|
|
3046
|
+
family: "archive",
|
|
3047
|
+
args: [
|
|
3048
|
+
{ name: "blockHash", type: "H256" },
|
|
3049
|
+
{ name: "items", type: "StorageItemInput[]" },
|
|
3050
|
+
{ name: "childTrie", type: "string", optional: true }
|
|
3051
|
+
],
|
|
3052
|
+
subscription: true
|
|
3053
|
+
},
|
|
3054
|
+
chainHead_v1_follow: {
|
|
3055
|
+
description: "Pin chainHead and stream block events. Requires a follow session.",
|
|
3056
|
+
family: "chainHead",
|
|
3057
|
+
args: [{ name: "withRuntime", type: "bool" }],
|
|
3058
|
+
subscription: true
|
|
3059
|
+
},
|
|
3060
|
+
transaction_v1_broadcast: {
|
|
3061
|
+
description: "Broadcast a signed extrinsic and watch its status.",
|
|
3062
|
+
family: "transaction",
|
|
3063
|
+
args: [{ name: "extrinsic", type: "hex" }],
|
|
3064
|
+
dangerous: true,
|
|
3065
|
+
subscription: true
|
|
3066
|
+
}
|
|
3067
|
+
};
|
|
3068
|
+
});
|
|
3069
|
+
|
|
2562
3070
|
// src/core/hash.ts
|
|
2563
3071
|
import { blake2b as blake2b2 } from "@noble/hashes/blake2.js";
|
|
2564
3072
|
import { sha256 } from "@noble/hashes/sha2.js";
|
|
@@ -2742,11 +3250,8 @@ async function generateCompletions(currentWord, precedingWords) {
|
|
|
2742
3250
|
if (firstArg === "hash") {
|
|
2743
3251
|
return filterPrefix(getAlgorithmNames(), currentWord);
|
|
2744
3252
|
}
|
|
2745
|
-
if (firstArg === "parachain") {
|
|
2746
|
-
|
|
2747
|
-
return filterPrefix(["child", "sibling"], currentWord);
|
|
2748
|
-
}
|
|
2749
|
-
return [];
|
|
3253
|
+
if (firstArg === "account" && prevWord === "--parachain-type") {
|
|
3254
|
+
return filterPrefix(["child", "sibling"], currentWord);
|
|
2750
3255
|
}
|
|
2751
3256
|
return completeDotpath(currentWord, config, knownChains, precedingWords);
|
|
2752
3257
|
}
|
|
@@ -2789,6 +3294,9 @@ async function completeDotpath(currentWord, config, knownChains, precedingWords)
|
|
|
2789
3294
|
if (category === "extensions") {
|
|
2790
3295
|
return completeExtensionsCategory(first, numComplete, endsWithDot, currentWord, config, chainFromFlag);
|
|
2791
3296
|
}
|
|
3297
|
+
if (category === "rpc") {
|
|
3298
|
+
return completeRpcCategory(first, numComplete, endsWithDot, currentWord, chainFromFlag);
|
|
3299
|
+
}
|
|
2792
3300
|
if (numComplete === 1 && endsWithDot) {
|
|
2793
3301
|
const chainName = chainFromFlag;
|
|
2794
3302
|
if (!chainName)
|
|
@@ -2848,6 +3356,9 @@ async function completeDotpath(currentWord, config, knownChains, precedingWords)
|
|
|
2848
3356
|
if (category === "extensions") {
|
|
2849
3357
|
return completeExtensionsCategory(`${first}.${completeSegments[1]}`, numComplete - 1, endsWithDot, currentWord, config, chainName);
|
|
2850
3358
|
}
|
|
3359
|
+
if (category === "rpc") {
|
|
3360
|
+
return completeRpcCategory(`${first}.${completeSegments[1]}`, numComplete - 1, endsWithDot, currentWord, chainName);
|
|
3361
|
+
}
|
|
2851
3362
|
const pallets = await loadPallets(config, chainName);
|
|
2852
3363
|
if (!pallets)
|
|
2853
3364
|
return [];
|
|
@@ -2921,6 +3432,24 @@ async function completeExtensionsCategory(prefix, numComplete, endsWithDot, curr
|
|
|
2921
3432
|
}
|
|
2922
3433
|
return [];
|
|
2923
3434
|
}
|
|
3435
|
+
async function completeRpcCategory(prefix, numComplete, endsWithDot, currentWord, chainNameOverride) {
|
|
3436
|
+
let names;
|
|
3437
|
+
if (chainNameOverride) {
|
|
3438
|
+
const cached = await loadRpcMethods(chainNameOverride);
|
|
3439
|
+
names = cached?.methods ?? Object.keys(RPC_REGISTRY);
|
|
3440
|
+
} else {
|
|
3441
|
+
names = Object.keys(RPC_REGISTRY);
|
|
3442
|
+
}
|
|
3443
|
+
if (numComplete === 1 && endsWithDot) {
|
|
3444
|
+
const candidates = names.map((n) => `${prefix}.${n}`);
|
|
3445
|
+
return filterPrefix(candidates, currentWord.slice(0, -1));
|
|
3446
|
+
}
|
|
3447
|
+
if (numComplete === 1 && !endsWithDot) {
|
|
3448
|
+
const candidates = names.map((n) => `${prefix}.${n}`);
|
|
3449
|
+
return filterPrefix(candidates, currentWord);
|
|
3450
|
+
}
|
|
3451
|
+
return [];
|
|
3452
|
+
}
|
|
2924
3453
|
var CATEGORIES2, CATEGORY_ALIASES2, NAMED_COMMANDS, CHAIN_SUBCOMMANDS, ACCOUNT_SUBCOMMANDS, GLOBAL_OPTIONS, TX_OPTIONS, QUERY_OPTIONS;
|
|
2925
3454
|
var init_complete = __esm(() => {
|
|
2926
3455
|
init_accounts_store();
|
|
@@ -2928,7 +3457,17 @@ var init_complete = __esm(() => {
|
|
|
2928
3457
|
init_accounts();
|
|
2929
3458
|
init_hash();
|
|
2930
3459
|
init_metadata();
|
|
2931
|
-
|
|
3460
|
+
init_rpc_registry();
|
|
3461
|
+
CATEGORIES2 = [
|
|
3462
|
+
"query",
|
|
3463
|
+
"tx",
|
|
3464
|
+
"const",
|
|
3465
|
+
"events",
|
|
3466
|
+
"errors",
|
|
3467
|
+
"apis",
|
|
3468
|
+
"extensions",
|
|
3469
|
+
"rpc"
|
|
3470
|
+
];
|
|
2932
3471
|
CATEGORY_ALIASES2 = {
|
|
2933
3472
|
query: "query",
|
|
2934
3473
|
tx: "tx",
|
|
@@ -2943,9 +3482,10 @@ var init_complete = __esm(() => {
|
|
|
2943
3482
|
api: "apis",
|
|
2944
3483
|
extensions: "extensions",
|
|
2945
3484
|
extension: "extensions",
|
|
2946
|
-
ext: "extensions"
|
|
3485
|
+
ext: "extensions",
|
|
3486
|
+
rpc: "rpc"
|
|
2947
3487
|
};
|
|
2948
|
-
NAMED_COMMANDS = ["chain", "account", "inspect", "hash", "sign", "
|
|
3488
|
+
NAMED_COMMANDS = ["chain", "account", "inspect", "hash", "sign", "completions"];
|
|
2949
3489
|
CHAIN_SUBCOMMANDS = ["add", "info", "list", "remove", "update"];
|
|
2950
3490
|
ACCOUNT_SUBCOMMANDS = [
|
|
2951
3491
|
"add",
|
|
@@ -2977,23 +3517,94 @@ var init_complete = __esm(() => {
|
|
|
2977
3517
|
// src/cli.ts
|
|
2978
3518
|
import cac from "cac";
|
|
2979
3519
|
// package.json
|
|
2980
|
-
var version = "1.
|
|
3520
|
+
var version = "1.18.0";
|
|
2981
3521
|
|
|
2982
3522
|
// src/commands/account.ts
|
|
2983
3523
|
init_accounts_store();
|
|
2984
3524
|
init_accounts();
|
|
2985
3525
|
init_output();
|
|
2986
3526
|
import { readFile as readFile3, writeFile as writeFile3 } from "node:fs/promises";
|
|
3527
|
+
|
|
3528
|
+
// src/core/pallet.ts
|
|
3529
|
+
init_errors();
|
|
3530
|
+
var MODL_PREFIX = new Uint8Array([109, 111, 100, 108]);
|
|
3531
|
+
var PALLET_ID_BYTES = 8;
|
|
3532
|
+
function derivePalletAccount(palletId) {
|
|
3533
|
+
if (palletId.length !== PALLET_ID_BYTES) {
|
|
3534
|
+
throw new CliError(`PalletId must be exactly ${PALLET_ID_BYTES} bytes (got ${palletId.length}).`);
|
|
3535
|
+
}
|
|
3536
|
+
const result = new Uint8Array(32);
|
|
3537
|
+
result.set(MODL_PREFIX, 0);
|
|
3538
|
+
result.set(palletId, 4);
|
|
3539
|
+
return result;
|
|
3540
|
+
}
|
|
3541
|
+
function parsePalletId(input) {
|
|
3542
|
+
if (input.startsWith("0x") || input.startsWith("0X")) {
|
|
3543
|
+
const hex = input.slice(2);
|
|
3544
|
+
if (hex.length !== PALLET_ID_BYTES * 2) {
|
|
3545
|
+
throw new CliError(`Invalid PalletId hex "${input}". Must be 0x followed by exactly ${PALLET_ID_BYTES * 2} hex characters.`);
|
|
3546
|
+
}
|
|
3547
|
+
if (!/^[0-9a-fA-F]+$/.test(hex)) {
|
|
3548
|
+
throw new CliError(`Invalid PalletId hex "${input}". Contains non-hex characters.`);
|
|
3549
|
+
}
|
|
3550
|
+
const bytes2 = new Uint8Array(PALLET_ID_BYTES);
|
|
3551
|
+
for (let i = 0;i < PALLET_ID_BYTES; i++) {
|
|
3552
|
+
bytes2[i] = parseInt(hex.slice(i * 2, i * 2 + 2), 16);
|
|
3553
|
+
}
|
|
3554
|
+
return bytes2;
|
|
3555
|
+
}
|
|
3556
|
+
if (input.length !== PALLET_ID_BYTES) {
|
|
3557
|
+
throw new CliError(`Invalid PalletId "${input}". Must be ${PALLET_ID_BYTES} ASCII characters or 0x-prefixed hex.`);
|
|
3558
|
+
}
|
|
3559
|
+
const bytes = new Uint8Array(PALLET_ID_BYTES);
|
|
3560
|
+
for (let i = 0;i < PALLET_ID_BYTES; i++) {
|
|
3561
|
+
const code = input.charCodeAt(i);
|
|
3562
|
+
if (code > 127) {
|
|
3563
|
+
throw new CliError(`Invalid PalletId "${input}". ASCII form must contain only ASCII bytes.`);
|
|
3564
|
+
}
|
|
3565
|
+
bytes[i] = code;
|
|
3566
|
+
}
|
|
3567
|
+
return bytes;
|
|
3568
|
+
}
|
|
3569
|
+
function formatPalletId(palletId) {
|
|
3570
|
+
const allPrintable = palletId.every((b) => b >= 32 && b <= 126);
|
|
3571
|
+
if (allPrintable) {
|
|
3572
|
+
return Array.from(palletId, (b) => String.fromCharCode(b)).join("");
|
|
3573
|
+
}
|
|
3574
|
+
return `0x${Array.from(palletId, (b) => b.toString(16).padStart(2, "0")).join("")}`;
|
|
3575
|
+
}
|
|
3576
|
+
|
|
3577
|
+
// src/core/parachain.ts
|
|
3578
|
+
var SOVEREIGN_ACCOUNT_TYPES = ["child", "sibling"];
|
|
3579
|
+
var PREFIXES = {
|
|
3580
|
+
child: new Uint8Array([112, 97, 114, 97]),
|
|
3581
|
+
sibling: new Uint8Array([115, 105, 98, 108])
|
|
3582
|
+
};
|
|
3583
|
+
function deriveSovereignAccount(paraId, type) {
|
|
3584
|
+
const result = new Uint8Array(32);
|
|
3585
|
+
result.set(PREFIXES[type], 0);
|
|
3586
|
+
new DataView(result.buffer).setUint32(4, paraId, true);
|
|
3587
|
+
return result;
|
|
3588
|
+
}
|
|
3589
|
+
function isValidParaId(value) {
|
|
3590
|
+
return Number.isInteger(value) && value >= 0 && value <= 4294967295;
|
|
3591
|
+
}
|
|
3592
|
+
|
|
3593
|
+
// src/commands/account.ts
|
|
2987
3594
|
var ACCOUNT_HELP = `
|
|
2988
3595
|
${BOLD}Usage:${RESET}
|
|
2989
3596
|
$ dot account add <name> <ss58|hex> Add a watch-only address (no secret)
|
|
2990
3597
|
$ dot account add <name> --secret <s> [--path <derivation>] Import from BIP39 mnemonic
|
|
2991
3598
|
$ dot account add <name> --env <VAR> [--path <derivation>] Import account backed by env variable
|
|
3599
|
+
$ dot account add <name> --parachain <id> --parachain-type <t> Derive a parachain sovereign (t = child|sibling)
|
|
3600
|
+
$ dot account add <name> --pallet-id <8 chars or 0x hex> Derive a pallet sovereign (e.g. py/trsry)
|
|
2992
3601
|
$ dot account create|new <name> [--path <derivation>] Create a new account
|
|
2993
3602
|
$ dot account import <file> Batch-import accounts from a file
|
|
2994
3603
|
$ dot account export [names...] Export accounts to stdout
|
|
2995
3604
|
$ dot account derive <source> <new-name> --path <derivation> Derive a child account
|
|
2996
3605
|
$ dot account inspect <input> [--prefix <N>] [--show-secret] Inspect an account/address/key
|
|
3606
|
+
$ dot account inspect --pallet-id <id> [--prefix <N>] Derive a pallet sovereign (no save — script-friendly)
|
|
3607
|
+
$ dot account inspect --parachain <id> --parachain-type <t> Derive a parachain sovereign (no save — script-friendly)
|
|
2997
3608
|
$ dot account list List all accounts
|
|
2998
3609
|
$ dot account remove|delete <name> [name2] ... Remove stored account(s)
|
|
2999
3610
|
|
|
@@ -3001,6 +3612,10 @@ ${BOLD}Examples:${RESET}
|
|
|
3001
3612
|
$ dot account add treasury 5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY
|
|
3002
3613
|
$ dot account add treasury --secret "word1 word2 ... word12"
|
|
3003
3614
|
$ dot account add ci-signer --env MY_SECRET --path //ci
|
|
3615
|
+
$ dot account add Treasury --pallet-id py/trsry
|
|
3616
|
+
$ dot account add Bounties --pallet-id 0x70792f626f756e74
|
|
3617
|
+
$ dot account add People --parachain 1004 --parachain-type child
|
|
3618
|
+
$ dot account add People-Sibling --parachain 1004 --parachain-type sibling
|
|
3004
3619
|
$ dot account create my-validator
|
|
3005
3620
|
$ dot account create my-staking --path //staking
|
|
3006
3621
|
$ dot account create multi --path //polkadot//0/wallet
|
|
@@ -3016,6 +3631,8 @@ ${BOLD}Examples:${RESET}
|
|
|
3016
3631
|
$ dot account inspect dave --show-secret
|
|
3017
3632
|
$ dot account inspect 5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY
|
|
3018
3633
|
$ dot account inspect 0xd435...a27d --prefix 0
|
|
3634
|
+
$ dot account inspect --pallet-id py/trsry --prefix 0
|
|
3635
|
+
$ dot account inspect --parachain 1004 --parachain-type child
|
|
3019
3636
|
$ dot account list
|
|
3020
3637
|
$ dot account remove my-validator stale-key
|
|
3021
3638
|
|
|
@@ -3024,7 +3641,7 @@ ${YELLOW}Note: Secrets are stored unencrypted in ~/.polkadot/accounts.json.
|
|
|
3024
3641
|
Hex seed import (0x...) is not supported via CLI.${RESET}
|
|
3025
3642
|
`.trimStart();
|
|
3026
3643
|
function registerAccountCommands(cli) {
|
|
3027
|
-
cli.command("account [action] [...names]", "Manage local accounts (create, import, list, remove, export)").alias("accounts").option("--secret <value>", "Secret key (mnemonic or hex seed) for import").option("--env <varName>", "Environment variable name holding the secret").option("--path <derivation>", "Derivation path (e.g. //staking, //polkadot//0/wallet)").option("--prefix <number>", "SS58 prefix for address encoding (default: 42)").option("--file <path>", "Input/output file for batch import/export").option("--overwrite", "Overwrite existing accounts on batch import").option("--dry-run", "Preview batch import without applying changes").option("--include-secrets", "Include secrets in export (redacted by default)").option("--watch-only", "Export only watch-only accounts").option("--show-secret", "Reveal the 64-byte sr25519 expanded private key (inspect only)").action(async (action, names, opts) => {
|
|
3644
|
+
cli.command("account [action] [...names]", "Manage local accounts (create, import, list, remove, export)").alias("accounts").option("--secret <value>", "Secret key (mnemonic or hex seed) for import").option("--env <varName>", "Environment variable name holding the secret").option("--path <derivation>", "Derivation path (e.g. //staking, //polkadot//0/wallet)").option("--parachain <id>", "Derive a parachain sovereign account (requires --parachain-type)").option("--parachain-type <type>", "Parachain sovereign type: child or sibling").option("--pallet-id <id>", "Derive a pallet sovereign account from an 8-byte PalletId").option("--prefix <number>", "SS58 prefix for address encoding (default: 42)").option("--file <path>", "Input/output file for batch import/export").option("--overwrite", "Overwrite existing accounts on batch import").option("--dry-run", "Preview batch import without applying changes").option("--include-secrets", "Include secrets in export (redacted by default)").option("--watch-only", "Export only watch-only accounts").option("--show-secret", "Reveal the 64-byte sr25519 expanded private key (inspect only)").action(async (action, names, opts) => {
|
|
3028
3645
|
if (!action) {
|
|
3029
3646
|
if (process.argv[2] === "accounts")
|
|
3030
3647
|
return accountList(opts);
|
|
@@ -3036,8 +3653,13 @@ function registerAccountCommands(cli) {
|
|
|
3036
3653
|
case "create":
|
|
3037
3654
|
return accountCreate(names[0], opts);
|
|
3038
3655
|
case "add":
|
|
3039
|
-
if (opts.secret || opts.env)
|
|
3656
|
+
if (opts.secret || opts.env) {
|
|
3657
|
+
const hasDerivation = opts.parachain != null || opts.palletId != null || process.argv.includes("--parachain") || process.argv.includes("--pallet-id") || process.argv.some((a) => a.startsWith("--parachain=") || a.startsWith("--pallet-id="));
|
|
3658
|
+
if (hasDerivation) {
|
|
3659
|
+
throw new Error("Derivation flags (--parachain, --pallet-id) cannot be combined with --secret or --env. A derived sovereign account has no secret.");
|
|
3660
|
+
}
|
|
3040
3661
|
return accountImport(names[0], opts);
|
|
3662
|
+
}
|
|
3041
3663
|
return accountAddWatchOnly(names[0], names[1], opts);
|
|
3042
3664
|
case "import":
|
|
3043
3665
|
return accountBatchImport(names[0], opts);
|
|
@@ -3193,10 +3815,16 @@ async function accountAddWatchOnly(name, address, opts = {}) {
|
|
|
3193
3815
|
console.error("Usage: dot account add <name> <ss58-address|0x-public-key>");
|
|
3194
3816
|
process.exit(1);
|
|
3195
3817
|
}
|
|
3196
|
-
|
|
3818
|
+
const sovereignSource = resolveSovereignSource(opts);
|
|
3819
|
+
if (sovereignSource && address) {
|
|
3820
|
+
throw new Error("Cannot combine a positional address with --parachain or --pallet-id. Pass either an address OR a derivation flag, not both.");
|
|
3821
|
+
}
|
|
3822
|
+
if (!sovereignSource && !address) {
|
|
3197
3823
|
console.error(`Address is required.
|
|
3198
3824
|
`);
|
|
3199
3825
|
console.error("Usage: dot account add <name> <ss58-address|0x-public-key>");
|
|
3826
|
+
console.error(" dot account add <name> --parachain <id> --parachain-type <child|sibling>");
|
|
3827
|
+
console.error(" dot account add <name> --pallet-id <8 chars or 0x hex>");
|
|
3200
3828
|
process.exit(1);
|
|
3201
3829
|
}
|
|
3202
3830
|
if (isDevAccount(name)) {
|
|
@@ -3207,7 +3835,10 @@ async function accountAddWatchOnly(name, address, opts = {}) {
|
|
|
3207
3835
|
throw new Error(`Account "${name}" already exists.`);
|
|
3208
3836
|
}
|
|
3209
3837
|
let hexPub;
|
|
3210
|
-
if (
|
|
3838
|
+
if (sovereignSource) {
|
|
3839
|
+
const accountId = sovereignSource.kind === "parachain" ? deriveSovereignAccount(sovereignSource.paraId, sovereignSource.type) : derivePalletAccount(sovereignSource.palletId);
|
|
3840
|
+
hexPub = publicKeyToHex(accountId);
|
|
3841
|
+
} else if (isHexPublicKey(address)) {
|
|
3211
3842
|
hexPub = address;
|
|
3212
3843
|
} else {
|
|
3213
3844
|
try {
|
|
@@ -3217,21 +3848,99 @@ async function accountAddWatchOnly(name, address, opts = {}) {
|
|
|
3217
3848
|
throw new Error(`Invalid address "${address}". Expected an SS58 address or 0x-prefixed 32-byte hex public key.`);
|
|
3218
3849
|
}
|
|
3219
3850
|
}
|
|
3851
|
+
let persistedSource;
|
|
3852
|
+
if (sovereignSource?.kind === "pallet") {
|
|
3853
|
+
persistedSource = {
|
|
3854
|
+
kind: "pallet",
|
|
3855
|
+
palletId: `0x${Array.from(sovereignSource.palletId, (b) => b.toString(16).padStart(2, "0")).join("")}`
|
|
3856
|
+
};
|
|
3857
|
+
} else if (sovereignSource?.kind === "parachain") {
|
|
3858
|
+
persistedSource = {
|
|
3859
|
+
kind: "parachain",
|
|
3860
|
+
paraId: sovereignSource.paraId,
|
|
3861
|
+
type: sovereignSource.type
|
|
3862
|
+
};
|
|
3863
|
+
}
|
|
3220
3864
|
accountsFile.accounts.push({
|
|
3221
3865
|
name,
|
|
3222
3866
|
publicKey: hexPub,
|
|
3223
|
-
derivationPath: ""
|
|
3867
|
+
derivationPath: "",
|
|
3868
|
+
...persistedSource ? { source: persistedSource } : {}
|
|
3224
3869
|
});
|
|
3225
3870
|
await saveAccounts(accountsFile);
|
|
3226
3871
|
if (isJsonOutput(opts)) {
|
|
3227
|
-
|
|
3872
|
+
const payload = {
|
|
3873
|
+
name,
|
|
3874
|
+
address: toSs58(hexPub),
|
|
3875
|
+
watchOnly: true
|
|
3876
|
+
};
|
|
3877
|
+
if (sovereignSource?.kind === "parachain") {
|
|
3878
|
+
payload.derivation = {
|
|
3879
|
+
kind: "parachain",
|
|
3880
|
+
paraId: sovereignSource.paraId,
|
|
3881
|
+
type: sovereignSource.type
|
|
3882
|
+
};
|
|
3883
|
+
} else if (sovereignSource?.kind === "pallet") {
|
|
3884
|
+
payload.derivation = {
|
|
3885
|
+
kind: "pallet",
|
|
3886
|
+
palletId: formatPalletId(sovereignSource.palletId),
|
|
3887
|
+
palletIdHex: `0x${Array.from(sovereignSource.palletId, (b) => b.toString(16).padStart(2, "0")).join("")}`
|
|
3888
|
+
};
|
|
3889
|
+
}
|
|
3890
|
+
console.log(formatJson(payload));
|
|
3228
3891
|
return;
|
|
3229
3892
|
}
|
|
3230
3893
|
printHeading("Account Added (watch-only)");
|
|
3231
3894
|
console.log(` ${BOLD}Name:${RESET} ${name}`);
|
|
3232
3895
|
console.log(` ${BOLD}Address:${RESET} ${toSs58(hexPub)}`);
|
|
3896
|
+
if (sovereignSource?.kind === "parachain") {
|
|
3897
|
+
console.log(` ${BOLD}Source:${RESET} parachain ${sovereignSource.paraId} (${sovereignSource.type} sovereign)`);
|
|
3898
|
+
} else if (sovereignSource?.kind === "pallet") {
|
|
3899
|
+
const display = formatPalletId(sovereignSource.palletId);
|
|
3900
|
+
const hex = `0x${Array.from(sovereignSource.palletId, (b) => b.toString(16).padStart(2, "0")).join("")}`;
|
|
3901
|
+
console.log(` ${BOLD}Source:${RESET} pallet ${display} (${hex})`);
|
|
3902
|
+
}
|
|
3233
3903
|
console.log();
|
|
3234
3904
|
}
|
|
3905
|
+
function rawArgValue(flag) {
|
|
3906
|
+
const argv = process.argv;
|
|
3907
|
+
for (let i = 0;i < argv.length; i++) {
|
|
3908
|
+
if (argv[i] === flag && i + 1 < argv.length)
|
|
3909
|
+
return argv[i + 1];
|
|
3910
|
+
const prefix = `${flag}=`;
|
|
3911
|
+
if (argv[i]?.startsWith(prefix))
|
|
3912
|
+
return argv[i].slice(prefix.length);
|
|
3913
|
+
}
|
|
3914
|
+
return;
|
|
3915
|
+
}
|
|
3916
|
+
function resolveSovereignSource(opts) {
|
|
3917
|
+
const rawPalletId = rawArgValue("--pallet-id") ?? opts.palletId;
|
|
3918
|
+
const rawParachain = rawArgValue("--parachain") ?? opts.parachain;
|
|
3919
|
+
if (rawParachain != null && rawPalletId != null) {
|
|
3920
|
+
throw new Error("--parachain and --pallet-id are mutually exclusive. Pass only one derivation flag.");
|
|
3921
|
+
}
|
|
3922
|
+
if (rawParachain != null) {
|
|
3923
|
+
const paraId = Number(rawParachain);
|
|
3924
|
+
if (!isValidParaId(paraId)) {
|
|
3925
|
+
throw new Error(`Invalid parachain ID "${rawParachain}". Must be a non-negative integer (0 to 4294967295).`);
|
|
3926
|
+
}
|
|
3927
|
+
if (!opts.parachainType) {
|
|
3928
|
+
throw new Error("--parachain-type is required when --parachain is given. Use --parachain-type child or --parachain-type sibling.");
|
|
3929
|
+
}
|
|
3930
|
+
const type = opts.parachainType.toLowerCase();
|
|
3931
|
+
if (type !== "child" && type !== "sibling") {
|
|
3932
|
+
throw new Error(`Unknown parachain account type "${opts.parachainType}". Valid types: child, sibling.`);
|
|
3933
|
+
}
|
|
3934
|
+
return { kind: "parachain", paraId, type };
|
|
3935
|
+
}
|
|
3936
|
+
if (rawPalletId != null) {
|
|
3937
|
+
return { kind: "pallet", palletId: parsePalletId(String(rawPalletId)) };
|
|
3938
|
+
}
|
|
3939
|
+
if (opts.parachainType != null) {
|
|
3940
|
+
throw new Error("--parachain-type requires --parachain.");
|
|
3941
|
+
}
|
|
3942
|
+
return;
|
|
3943
|
+
}
|
|
3235
3944
|
async function accountDerive(sourceName, newName, opts) {
|
|
3236
3945
|
if (!sourceName) {
|
|
3237
3946
|
console.error(`Source account name is required.
|
|
@@ -3315,69 +4024,134 @@ async function accountDerive(sourceName, newName, opts) {
|
|
|
3315
4024
|
console.log();
|
|
3316
4025
|
}
|
|
3317
4026
|
}
|
|
4027
|
+
function resolveAddress(account) {
|
|
4028
|
+
if (isWatchOnly(account)) {
|
|
4029
|
+
return account.publicKey ? toSs58(account.publicKey) : "n/a";
|
|
4030
|
+
}
|
|
4031
|
+
if (account.secret !== undefined && isEnvSecret(account.secret)) {
|
|
4032
|
+
const pubKey = account.publicKey || tryDerivePublicKey(account.secret.env, account.derivationPath) || "";
|
|
4033
|
+
return pubKey ? toSs58(pubKey) : "n/a";
|
|
4034
|
+
}
|
|
4035
|
+
return toSs58(account.publicKey);
|
|
4036
|
+
}
|
|
4037
|
+
function buildAttributes(account) {
|
|
4038
|
+
const attrs = [];
|
|
4039
|
+
if (account.derivationPath)
|
|
4040
|
+
attrs.push({ label: "path", value: account.derivationPath });
|
|
4041
|
+
if (account.secret !== undefined && isEnvSecret(account.secret)) {
|
|
4042
|
+
attrs.push({ label: "env", value: `$${account.secret.env}` });
|
|
4043
|
+
}
|
|
4044
|
+
if (account.source) {
|
|
4045
|
+
if (account.source.kind === "pallet") {
|
|
4046
|
+
const bytes = parsePalletId(account.source.palletId);
|
|
4047
|
+
attrs.push({
|
|
4048
|
+
label: "pallet-id",
|
|
4049
|
+
value: `${formatPalletId(bytes)} (${account.source.palletId})`
|
|
4050
|
+
});
|
|
4051
|
+
} else {
|
|
4052
|
+
attrs.push({ label: "parachain", value: String(account.source.paraId) });
|
|
4053
|
+
attrs.push({ label: "parachain-type", value: account.source.type });
|
|
4054
|
+
}
|
|
4055
|
+
}
|
|
4056
|
+
return attrs;
|
|
4057
|
+
}
|
|
4058
|
+
function buildRow(account) {
|
|
4059
|
+
return {
|
|
4060
|
+
account,
|
|
4061
|
+
kind: classifyAccount(account),
|
|
4062
|
+
address: resolveAddress(account),
|
|
4063
|
+
attributes: buildAttributes(account)
|
|
4064
|
+
};
|
|
4065
|
+
}
|
|
4066
|
+
var SECTION_ORDER = [
|
|
4067
|
+
{ kind: "signer", title: "Signers" },
|
|
4068
|
+
{ kind: "watch-only", title: "Watch-only" },
|
|
4069
|
+
{ kind: "pallet", title: "Pallet Sovereigns" },
|
|
4070
|
+
{ kind: "parachain", title: "Parachain Sovereigns" }
|
|
4071
|
+
];
|
|
4072
|
+
function printAccountSection(title, rows) {
|
|
4073
|
+
if (rows.length === 0)
|
|
4074
|
+
return;
|
|
4075
|
+
const nameWidth = Math.max(...rows.map((r) => r.name.length));
|
|
4076
|
+
printHeading(title);
|
|
4077
|
+
for (const row of rows) {
|
|
4078
|
+
const namePad = row.name.padEnd(nameWidth);
|
|
4079
|
+
console.log(` ${CYAN}${namePad}${RESET} ${row.address}`);
|
|
4080
|
+
if (row.attributes.length === 0)
|
|
4081
|
+
continue;
|
|
4082
|
+
const labelWidth = Math.max(...row.attributes.map((a) => a.label.length)) + 1;
|
|
4083
|
+
for (let i = 0;i < row.attributes.length; i++) {
|
|
4084
|
+
const isLast = i === row.attributes.length - 1;
|
|
4085
|
+
const connector = isLast ? "└─" : "├─";
|
|
4086
|
+
const labelText = `${row.attributes[i].label}:`.padEnd(labelWidth + 1);
|
|
4087
|
+
console.log(` ${DIM}${connector}${RESET} ${DIM}${labelText}${RESET}${row.attributes[i].value}`);
|
|
4088
|
+
}
|
|
4089
|
+
}
|
|
4090
|
+
}
|
|
3318
4091
|
async function accountList(opts = {}) {
|
|
3319
4092
|
const accountsFile = await loadAccounts();
|
|
3320
4093
|
if (isJsonOutput(opts)) {
|
|
3321
4094
|
const dev = DEV_NAMES.map((name) => ({
|
|
3322
4095
|
name: name.charAt(0).toUpperCase() + name.slice(1),
|
|
3323
|
-
address: getDevAddress(name)
|
|
4096
|
+
address: getDevAddress(name),
|
|
4097
|
+
kind: "dev"
|
|
3324
4098
|
}));
|
|
3325
4099
|
const stored = accountsFile.accounts.map((account) => {
|
|
3326
|
-
|
|
3327
|
-
|
|
3328
|
-
address = account.publicKey ? toSs58(account.publicKey) : undefined;
|
|
3329
|
-
} else if (account.secret !== undefined && isEnvSecret(account.secret)) {
|
|
3330
|
-
let pubKey = account.publicKey;
|
|
3331
|
-
if (!pubKey) {
|
|
3332
|
-
pubKey = tryDerivePublicKey(account.secret.env, account.derivationPath) ?? "";
|
|
3333
|
-
}
|
|
3334
|
-
address = pubKey ? toSs58(pubKey) : undefined;
|
|
3335
|
-
} else {
|
|
3336
|
-
address = toSs58(account.publicKey);
|
|
3337
|
-
}
|
|
3338
|
-
return {
|
|
4100
|
+
const kind = classifyAccount(account);
|
|
4101
|
+
const entry = {
|
|
3339
4102
|
name: account.name,
|
|
3340
|
-
address,
|
|
3341
|
-
|
|
3342
|
-
watchOnly: isWatchOnly(account)
|
|
3343
|
-
env: account.secret !== undefined && isEnvSecret(account.secret) ? account.secret.env : undefined
|
|
4103
|
+
address: resolveAddress(account),
|
|
4104
|
+
kind,
|
|
4105
|
+
watchOnly: isWatchOnly(account)
|
|
3344
4106
|
};
|
|
4107
|
+
if (account.derivationPath)
|
|
4108
|
+
entry.derivationPath = account.derivationPath;
|
|
4109
|
+
if (account.secret !== undefined && isEnvSecret(account.secret)) {
|
|
4110
|
+
entry.env = account.secret.env;
|
|
4111
|
+
}
|
|
4112
|
+
if (account.source) {
|
|
4113
|
+
if (account.source.kind === "pallet") {
|
|
4114
|
+
const bytes = parsePalletId(account.source.palletId);
|
|
4115
|
+
entry.source = {
|
|
4116
|
+
kind: "pallet",
|
|
4117
|
+
palletId: formatPalletId(bytes),
|
|
4118
|
+
palletIdHex: account.source.palletId
|
|
4119
|
+
};
|
|
4120
|
+
} else {
|
|
4121
|
+
entry.source = account.source;
|
|
4122
|
+
}
|
|
4123
|
+
}
|
|
4124
|
+
return entry;
|
|
3345
4125
|
});
|
|
3346
4126
|
console.log(formatJson({ dev, stored }));
|
|
3347
4127
|
return;
|
|
3348
4128
|
}
|
|
3349
|
-
|
|
3350
|
-
|
|
3351
|
-
|
|
3352
|
-
|
|
3353
|
-
|
|
4129
|
+
const devRows = DEV_NAMES.map((name) => ({
|
|
4130
|
+
name: name.charAt(0).toUpperCase() + name.slice(1),
|
|
4131
|
+
address: getDevAddress(name),
|
|
4132
|
+
attributes: []
|
|
4133
|
+
}));
|
|
4134
|
+
printAccountSection("Dev Accounts", devRows);
|
|
4135
|
+
const buckets = new Map;
|
|
4136
|
+
for (const account of accountsFile.accounts) {
|
|
4137
|
+
const row = buildRow(account);
|
|
4138
|
+
const arr = buckets.get(row.kind) ?? [];
|
|
4139
|
+
arr.push(row);
|
|
4140
|
+
buckets.set(row.kind, arr);
|
|
4141
|
+
}
|
|
4142
|
+
for (const { kind, title } of SECTION_ORDER) {
|
|
4143
|
+
const rows = buckets.get(kind);
|
|
4144
|
+
if (!rows || rows.length === 0)
|
|
4145
|
+
continue;
|
|
4146
|
+
printAccountSection(title, rows.map((r) => ({
|
|
4147
|
+
name: r.account.name,
|
|
4148
|
+
address: r.address,
|
|
4149
|
+
attributes: r.attributes
|
|
4150
|
+
})));
|
|
3354
4151
|
}
|
|
3355
|
-
if (accountsFile.accounts.length
|
|
3356
|
-
printHeading("Stored Accounts");
|
|
3357
|
-
for (const account of accountsFile.accounts) {
|
|
3358
|
-
let displayName = account.name;
|
|
3359
|
-
if (account.derivationPath) {
|
|
3360
|
-
displayName += ` (${account.derivationPath})`;
|
|
3361
|
-
}
|
|
3362
|
-
let address;
|
|
3363
|
-
if (isWatchOnly(account)) {
|
|
3364
|
-
displayName += " (watch-only)";
|
|
3365
|
-
address = account.publicKey ? toSs58(account.publicKey) : "n/a";
|
|
3366
|
-
} else if (account.secret !== undefined && isEnvSecret(account.secret)) {
|
|
3367
|
-
displayName += ` (env: ${account.secret.env})`;
|
|
3368
|
-
let pubKey = account.publicKey;
|
|
3369
|
-
if (!pubKey) {
|
|
3370
|
-
pubKey = tryDerivePublicKey(account.secret.env, account.derivationPath) ?? "";
|
|
3371
|
-
}
|
|
3372
|
-
address = pubKey ? toSs58(pubKey) : "n/a";
|
|
3373
|
-
} else {
|
|
3374
|
-
address = toSs58(account.publicKey);
|
|
3375
|
-
}
|
|
3376
|
-
printItem(displayName, address);
|
|
3377
|
-
}
|
|
3378
|
-
} else {
|
|
4152
|
+
if (accountsFile.accounts.length === 0) {
|
|
3379
4153
|
printHeading("Stored Accounts");
|
|
3380
|
-
console.log(
|
|
4154
|
+
console.log(` ${DIM}(none)${RESET}`);
|
|
3381
4155
|
}
|
|
3382
4156
|
console.log();
|
|
3383
4157
|
}
|
|
@@ -3425,10 +4199,20 @@ async function accountRemove(names, opts = {}) {
|
|
|
3425
4199
|
}
|
|
3426
4200
|
}
|
|
3427
4201
|
async function accountInspect(input, opts) {
|
|
3428
|
-
|
|
4202
|
+
const sovereignSource = resolveSovereignSource({
|
|
4203
|
+
parachain: opts.parachain,
|
|
4204
|
+
parachainType: opts.parachainType,
|
|
4205
|
+
palletId: opts.palletId
|
|
4206
|
+
});
|
|
4207
|
+
if (sovereignSource && input) {
|
|
4208
|
+
throw new Error("Cannot combine a positional input with --parachain or --pallet-id. Pass either an existing-account input OR a derivation flag, not both.");
|
|
4209
|
+
}
|
|
4210
|
+
if (!sovereignSource && !input) {
|
|
3429
4211
|
console.error(`Input is required.
|
|
3430
4212
|
`);
|
|
3431
4213
|
console.error("Usage: dot account inspect <name|ss58-address|0x-public-key> [--prefix <N>]");
|
|
4214
|
+
console.error(" dot account inspect --pallet-id <id> [--prefix <N>]");
|
|
4215
|
+
console.error(" dot account inspect --parachain <id> --parachain-type <child|sibling> [--prefix <N>]");
|
|
3432
4216
|
process.exit(1);
|
|
3433
4217
|
}
|
|
3434
4218
|
const prefix = opts.prefix != null ? Number(opts.prefix) : 42;
|
|
@@ -3440,11 +4224,32 @@ async function accountInspect(input, opts) {
|
|
|
3440
4224
|
let publicKeyHex;
|
|
3441
4225
|
let bandersnatch;
|
|
3442
4226
|
let hasSecret = false;
|
|
3443
|
-
|
|
4227
|
+
let storedAccount;
|
|
4228
|
+
let isDev = false;
|
|
4229
|
+
let virtualSource;
|
|
4230
|
+
if (sovereignSource) {
|
|
4231
|
+
if (sovereignSource.kind === "pallet") {
|
|
4232
|
+
const accountId = derivePalletAccount(sovereignSource.palletId);
|
|
4233
|
+
publicKeyHex = publicKeyToHex(accountId);
|
|
4234
|
+
virtualSource = {
|
|
4235
|
+
kind: "pallet",
|
|
4236
|
+
palletIdHex: `0x${Array.from(sovereignSource.palletId, (b) => b.toString(16).padStart(2, "0")).join("")}`
|
|
4237
|
+
};
|
|
4238
|
+
} else {
|
|
4239
|
+
const accountId = deriveSovereignAccount(sovereignSource.paraId, sovereignSource.type);
|
|
4240
|
+
publicKeyHex = publicKeyToHex(accountId);
|
|
4241
|
+
virtualSource = {
|
|
4242
|
+
kind: "parachain",
|
|
4243
|
+
paraId: sovereignSource.paraId,
|
|
4244
|
+
type: sovereignSource.type
|
|
4245
|
+
};
|
|
4246
|
+
}
|
|
4247
|
+
} else if (isDevAccount(input)) {
|
|
3444
4248
|
name = input.charAt(0).toUpperCase() + input.slice(1).toLowerCase();
|
|
3445
4249
|
const devAddr = getDevAddress(input);
|
|
3446
4250
|
publicKeyHex = publicKeyToHex(fromSs58(devAddr));
|
|
3447
4251
|
hasSecret = true;
|
|
4252
|
+
isDev = true;
|
|
3448
4253
|
} else {
|
|
3449
4254
|
const accountsFile = await loadAccounts();
|
|
3450
4255
|
const account = findAccount(accountsFile, input);
|
|
@@ -3452,6 +4257,7 @@ async function accountInspect(input, opts) {
|
|
|
3452
4257
|
name = account.name;
|
|
3453
4258
|
bandersnatch = account.bandersnatch;
|
|
3454
4259
|
hasSecret = account.secret !== undefined;
|
|
4260
|
+
storedAccount = account;
|
|
3455
4261
|
if (account.publicKey) {
|
|
3456
4262
|
publicKeyHex = account.publicKey;
|
|
3457
4263
|
} else if (account.secret !== undefined && isEnvSecret(account.secret)) {
|
|
@@ -3495,10 +4301,74 @@ async function accountInspect(input, opts) {
|
|
|
3495
4301
|
process.exit(1);
|
|
3496
4302
|
}
|
|
3497
4303
|
}
|
|
4304
|
+
let kindLabel;
|
|
4305
|
+
let sourceLine;
|
|
4306
|
+
let derivationLine;
|
|
4307
|
+
let envLine;
|
|
4308
|
+
if (virtualSource?.kind === "pallet") {
|
|
4309
|
+
kindLabel = "pallet sovereign";
|
|
4310
|
+
const bytes = parsePalletId(virtualSource.palletIdHex);
|
|
4311
|
+
sourceLine = `PalletId ${formatPalletId(bytes)} (${virtualSource.palletIdHex})`;
|
|
4312
|
+
} else if (virtualSource?.kind === "parachain") {
|
|
4313
|
+
kindLabel = `parachain sovereign (${virtualSource.type})`;
|
|
4314
|
+
sourceLine = `parachain ${virtualSource.paraId}`;
|
|
4315
|
+
} else if (isDev) {
|
|
4316
|
+
kindLabel = "dev";
|
|
4317
|
+
} else if (storedAccount) {
|
|
4318
|
+
const k = classifyAccount(storedAccount);
|
|
4319
|
+
if (k === "pallet" && storedAccount.source?.kind === "pallet") {
|
|
4320
|
+
kindLabel = "pallet sovereign";
|
|
4321
|
+
const bytes = parsePalletId(storedAccount.source.palletId);
|
|
4322
|
+
sourceLine = `PalletId ${formatPalletId(bytes)} (${storedAccount.source.palletId})`;
|
|
4323
|
+
} else if (k === "parachain" && storedAccount.source?.kind === "parachain") {
|
|
4324
|
+
kindLabel = `parachain sovereign (${storedAccount.source.type})`;
|
|
4325
|
+
sourceLine = `parachain ${storedAccount.source.paraId}`;
|
|
4326
|
+
} else if (k === "signer") {
|
|
4327
|
+
kindLabel = "signer";
|
|
4328
|
+
} else {
|
|
4329
|
+
kindLabel = "watch-only";
|
|
4330
|
+
}
|
|
4331
|
+
if (storedAccount.derivationPath)
|
|
4332
|
+
derivationLine = storedAccount.derivationPath;
|
|
4333
|
+
if (storedAccount.secret !== undefined && isEnvSecret(storedAccount.secret)) {
|
|
4334
|
+
envLine = `$${storedAccount.secret.env}`;
|
|
4335
|
+
}
|
|
4336
|
+
}
|
|
3498
4337
|
if (isJsonOutput(opts)) {
|
|
3499
4338
|
const result = { publicKey: publicKeyHex, ss58, prefix };
|
|
3500
4339
|
if (name)
|
|
3501
4340
|
result.name = name;
|
|
4341
|
+
if (kindLabel)
|
|
4342
|
+
result.kind = kindLabel;
|
|
4343
|
+
if (virtualSource?.kind === "pallet") {
|
|
4344
|
+
const bytes = parsePalletId(virtualSource.palletIdHex);
|
|
4345
|
+
result.source = {
|
|
4346
|
+
kind: "pallet",
|
|
4347
|
+
palletId: formatPalletId(bytes),
|
|
4348
|
+
palletIdHex: virtualSource.palletIdHex
|
|
4349
|
+
};
|
|
4350
|
+
} else if (virtualSource?.kind === "parachain") {
|
|
4351
|
+
result.source = {
|
|
4352
|
+
kind: "parachain",
|
|
4353
|
+
paraId: virtualSource.paraId,
|
|
4354
|
+
type: virtualSource.type
|
|
4355
|
+
};
|
|
4356
|
+
} else if (storedAccount?.source) {
|
|
4357
|
+
if (storedAccount.source.kind === "pallet") {
|
|
4358
|
+
const bytes = parsePalletId(storedAccount.source.palletId);
|
|
4359
|
+
result.source = {
|
|
4360
|
+
kind: "pallet",
|
|
4361
|
+
palletId: formatPalletId(bytes),
|
|
4362
|
+
palletIdHex: storedAccount.source.palletId
|
|
4363
|
+
};
|
|
4364
|
+
} else {
|
|
4365
|
+
result.source = storedAccount.source;
|
|
4366
|
+
}
|
|
4367
|
+
}
|
|
4368
|
+
if (derivationLine)
|
|
4369
|
+
result.derivationPath = derivationLine;
|
|
4370
|
+
if (envLine)
|
|
4371
|
+
result.env = envLine.replace(/^\$/, "");
|
|
3502
4372
|
if (bandersnatch && Object.keys(bandersnatch).length > 0)
|
|
3503
4373
|
result.bandersnatch = bandersnatch;
|
|
3504
4374
|
if (privateKeyHex)
|
|
@@ -3508,8 +4378,16 @@ async function accountInspect(input, opts) {
|
|
|
3508
4378
|
printHeading("Account Info");
|
|
3509
4379
|
if (name)
|
|
3510
4380
|
console.log(` ${BOLD}Name:${RESET} ${name}`);
|
|
4381
|
+
if (kindLabel)
|
|
4382
|
+
console.log(` ${BOLD}Kind:${RESET} ${kindLabel}`);
|
|
3511
4383
|
console.log(` ${BOLD}Public Key:${RESET} ${publicKeyHex}`);
|
|
3512
4384
|
console.log(` ${BOLD}SS58:${RESET} ${ss58}`);
|
|
4385
|
+
if (sourceLine)
|
|
4386
|
+
console.log(` ${BOLD}Source:${RESET} ${sourceLine}`);
|
|
4387
|
+
if (derivationLine)
|
|
4388
|
+
console.log(` ${BOLD}Derivation:${RESET} ${derivationLine}`);
|
|
4389
|
+
if (envLine)
|
|
4390
|
+
console.log(` ${BOLD}Env:${RESET} ${envLine}`);
|
|
3513
4391
|
if (bandersnatch && Object.keys(bandersnatch).length > 0) {
|
|
3514
4392
|
const entries = Object.entries(bandersnatch);
|
|
3515
4393
|
for (let i = 0;i < entries.length; i++) {
|
|
@@ -3813,6 +4691,53 @@ init_client();
|
|
|
3813
4691
|
init_metadata();
|
|
3814
4692
|
init_output();
|
|
3815
4693
|
import { readFile as readFile4, writeFile as writeFile4 } from "node:fs/promises";
|
|
4694
|
+
|
|
4695
|
+
// src/core/rpc.ts
|
|
4696
|
+
init_errors();
|
|
4697
|
+
import { createClient as createSubstrateClient } from "@polkadot-api/substrate-client";
|
|
4698
|
+
import { getWsProvider as getWsProvider2 } from "polkadot-api/ws";
|
|
4699
|
+
function suppressProviderNoise2() {
|
|
4700
|
+
const origError = console.error;
|
|
4701
|
+
console.error = (...args) => {
|
|
4702
|
+
if (typeof args[0] === "string" && args[0].includes("Unable to connect"))
|
|
4703
|
+
return;
|
|
4704
|
+
origError(...args);
|
|
4705
|
+
};
|
|
4706
|
+
return () => {
|
|
4707
|
+
console.error = origError;
|
|
4708
|
+
};
|
|
4709
|
+
}
|
|
4710
|
+
async function rpcRequest(rpcUrl, method, params, timeoutMs = 30000) {
|
|
4711
|
+
const restoreConsole = suppressProviderNoise2();
|
|
4712
|
+
const provider = getWsProvider2(rpcUrl, { timeout: 1e4 });
|
|
4713
|
+
const client = createSubstrateClient(provider);
|
|
4714
|
+
const controller = new AbortController;
|
|
4715
|
+
const timer = setTimeout(() => controller.abort(), timeoutMs);
|
|
4716
|
+
try {
|
|
4717
|
+
return await client.request(method, params, controller.signal);
|
|
4718
|
+
} catch (err) {
|
|
4719
|
+
if (err instanceof Error && /Unable to connect/i.test(err.message)) {
|
|
4720
|
+
throw new ConnectionError(`Could not reach RPC ${Array.isArray(rpcUrl) ? rpcUrl.join(", ") : rpcUrl}: ${err.message}`);
|
|
4721
|
+
}
|
|
4722
|
+
throw err;
|
|
4723
|
+
} finally {
|
|
4724
|
+
clearTimeout(timer);
|
|
4725
|
+
try {
|
|
4726
|
+
client.destroy();
|
|
4727
|
+
} catch {}
|
|
4728
|
+
setTimeout(restoreConsole, 100);
|
|
4729
|
+
}
|
|
4730
|
+
}
|
|
4731
|
+
async function fetchRpcMethods(rpcUrl) {
|
|
4732
|
+
const result = await rpcRequest(rpcUrl, "rpc_methods", []);
|
|
4733
|
+
if (!result || !Array.isArray(result.methods)) {
|
|
4734
|
+
throw new ConnectionError("Node returned an unexpected response for rpc_methods (no methods array).");
|
|
4735
|
+
}
|
|
4736
|
+
return { methods: result.methods, version: result.version ?? 1 };
|
|
4737
|
+
}
|
|
4738
|
+
|
|
4739
|
+
// src/commands/chain.ts
|
|
4740
|
+
init_rpc_registry();
|
|
3816
4741
|
var CHAIN_HELP = `
|
|
3817
4742
|
${BOLD}Usage:${RESET}
|
|
3818
4743
|
$ dot chain add <name> --rpc <url> Add a chain via WebSocket RPC
|
|
@@ -3881,6 +4806,18 @@ function registerChainCommands(cli) {
|
|
|
3881
4806
|
}
|
|
3882
4807
|
});
|
|
3883
4808
|
}
|
|
4809
|
+
async function refreshRpcMethods(chainName, rpcUrl, silent = false) {
|
|
4810
|
+
try {
|
|
4811
|
+
const { methods, version: version2 } = await fetchRpcMethods(rpcUrl);
|
|
4812
|
+
await saveRpcMethods(chainName, methods, version2);
|
|
4813
|
+
} catch (err) {
|
|
4814
|
+
if (!silent) {
|
|
4815
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
4816
|
+
process.stderr.write(`${YELLOW}Warning:${RESET} could not fetch rpc_methods — ${msg}
|
|
4817
|
+
`);
|
|
4818
|
+
}
|
|
4819
|
+
}
|
|
4820
|
+
}
|
|
3884
4821
|
async function chainAdd(name, opts) {
|
|
3885
4822
|
if (!name) {
|
|
3886
4823
|
console.error(`Chain name is required.
|
|
@@ -3909,6 +4846,7 @@ async function chainAdd(name, opts) {
|
|
|
3909
4846
|
process.stderr.write(`Fetching metadata...
|
|
3910
4847
|
`);
|
|
3911
4848
|
await fetchMetadataFromChain(clientHandle, name);
|
|
4849
|
+
await refreshRpcMethods(name, opts.rpc);
|
|
3912
4850
|
if (opts.relay) {
|
|
3913
4851
|
const config2 = await loadConfig();
|
|
3914
4852
|
const relayResolved = findChainName(config2, opts.relay);
|
|
@@ -4049,6 +4987,12 @@ async function chainInfo(name, opts = {}) {
|
|
|
4049
4987
|
const rpcs = Array.isArray(chain.rpc) ? chain.rpc : [chain.rpc];
|
|
4050
4988
|
const parachains = Object.entries(config.chains).filter(([, c]) => c.relay === resolved).map(([n, c]) => ({ name: n, parachainId: c.parachainId }));
|
|
4051
4989
|
const fingerprint = await loadMetadataFingerprint(resolved);
|
|
4990
|
+
const rpcCache = await loadRpcMethods(resolved);
|
|
4991
|
+
const rpcSummary = rpcCache ? {
|
|
4992
|
+
count: rpcCache.methods.length,
|
|
4993
|
+
fetchedAt: rpcCache.fetchedAt,
|
|
4994
|
+
byFamily: countByFamily(rpcCache.methods)
|
|
4995
|
+
} : null;
|
|
4052
4996
|
if (isJsonOutput(opts)) {
|
|
4053
4997
|
console.log(formatJson({
|
|
4054
4998
|
name: resolved,
|
|
@@ -4060,7 +5004,8 @@ async function chainInfo(name, opts = {}) {
|
|
|
4060
5004
|
specName: fingerprint.specName,
|
|
4061
5005
|
specVersion: fingerprint.specVersion,
|
|
4062
5006
|
fetchedAt: fingerprint.fetchedAt
|
|
4063
|
-
} : null
|
|
5007
|
+
} : null,
|
|
5008
|
+
rpcMethods: rpcSummary
|
|
4064
5009
|
}));
|
|
4065
5010
|
return;
|
|
4066
5011
|
}
|
|
@@ -4088,6 +5033,22 @@ async function chainInfo(name, opts = {}) {
|
|
|
4088
5033
|
} else {
|
|
4089
5034
|
console.log(` ${DIM}not cached — run \`dot chain update ${resolved}\`${RESET}`);
|
|
4090
5035
|
}
|
|
5036
|
+
console.log(` ${CYAN}rpc methods:${RESET}`);
|
|
5037
|
+
if (rpcSummary) {
|
|
5038
|
+
const families = Object.entries(rpcSummary.byFamily).map(([f, n]) => `${f}: ${n}`).join(", ");
|
|
5039
|
+
console.log(` ${rpcSummary.count} ${DIM}(${families})${RESET}`);
|
|
5040
|
+
console.log(` ${DIM}cached ${rpcSummary.fetchedAt}${RESET}`);
|
|
5041
|
+
} else {
|
|
5042
|
+
console.log(` ${DIM}not cached — run \`dot chain update ${resolved}\`${RESET}`);
|
|
5043
|
+
}
|
|
5044
|
+
}
|
|
5045
|
+
function countByFamily(methods) {
|
|
5046
|
+
const counts = {};
|
|
5047
|
+
for (const m of methods) {
|
|
5048
|
+
const family = RPC_REGISTRY[m]?.family ?? inferFamily(m);
|
|
5049
|
+
counts[family] = (counts[family] ?? 0) + 1;
|
|
5050
|
+
}
|
|
5051
|
+
return counts;
|
|
4091
5052
|
}
|
|
4092
5053
|
async function chainUpdate(name, opts) {
|
|
4093
5054
|
const config = await loadConfig();
|
|
@@ -4107,6 +5068,7 @@ async function chainUpdate(name, opts) {
|
|
|
4107
5068
|
process.stderr.write(`Fetching metadata...
|
|
4108
5069
|
`);
|
|
4109
5070
|
await fetchMetadataFromChain(clientHandle, chainName);
|
|
5071
|
+
await refreshRpcMethods(chainName, opts.rpc ?? chainConfig.rpc);
|
|
4110
5072
|
if (isJsonOutput(opts)) {
|
|
4111
5073
|
console.log(formatJson({ action: "updated", chain: chainName }));
|
|
4112
5074
|
} else {
|
|
@@ -4136,6 +5098,7 @@ async function updateChainsMetadata(config, chainNames) {
|
|
|
4136
5098
|
const clientHandle = await createChainClient(chainName, chainConfig);
|
|
4137
5099
|
try {
|
|
4138
5100
|
await fetchMetadataFromChain(clientHandle, chainName);
|
|
5101
|
+
await refreshRpcMethods(chainName, chainConfig.rpc, true);
|
|
4139
5102
|
} finally {
|
|
4140
5103
|
clientHandle.destroy();
|
|
4141
5104
|
}
|
|
@@ -5687,24 +6650,6 @@ function registerMetadataCommand(cli) {
|
|
|
5687
6650
|
// src/commands/parachain.ts
|
|
5688
6651
|
init_accounts();
|
|
5689
6652
|
init_output();
|
|
5690
|
-
|
|
5691
|
-
// src/core/parachain.ts
|
|
5692
|
-
var SOVEREIGN_ACCOUNT_TYPES = ["child", "sibling"];
|
|
5693
|
-
var PREFIXES = {
|
|
5694
|
-
child: new Uint8Array([112, 97, 114, 97]),
|
|
5695
|
-
sibling: new Uint8Array([115, 105, 98, 108])
|
|
5696
|
-
};
|
|
5697
|
-
function deriveSovereignAccount(paraId, type) {
|
|
5698
|
-
const result = new Uint8Array(32);
|
|
5699
|
-
result.set(PREFIXES[type], 0);
|
|
5700
|
-
new DataView(result.buffer).setUint32(4, paraId, true);
|
|
5701
|
-
return result;
|
|
5702
|
-
}
|
|
5703
|
-
function isValidParaId(value) {
|
|
5704
|
-
return Number.isInteger(value) && value >= 0 && value <= 4294967295;
|
|
5705
|
-
}
|
|
5706
|
-
|
|
5707
|
-
// src/commands/parachain.ts
|
|
5708
6653
|
init_errors();
|
|
5709
6654
|
function printParachainHelp() {
|
|
5710
6655
|
console.log(`${BOLD}Usage:${RESET} dot parachain <paraId> [options]
|
|
@@ -5734,6 +6679,7 @@ function validateType(type) {
|
|
|
5734
6679
|
}
|
|
5735
6680
|
function registerParachainCommand(cli) {
|
|
5736
6681
|
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) => {
|
|
6682
|
+
console.error("Warning: `dot parachain` is deprecated; use `dot account inspect --parachain <id> --parachain-type <child|sibling>` instead. Will be removed in a future release.");
|
|
5737
6683
|
if (!paraIdStr) {
|
|
5738
6684
|
printParachainHelp();
|
|
5739
6685
|
return;
|
|
@@ -5947,6 +6893,168 @@ async function parseStorageKeys(meta, palletName2, storageItem, args) {
|
|
|
5947
6893
|
return Promise.all(args.map((arg) => parseTypedArg(meta, keyEntry, arg)));
|
|
5948
6894
|
}
|
|
5949
6895
|
|
|
6896
|
+
// src/commands/rpc.ts
|
|
6897
|
+
init_store();
|
|
6898
|
+
init_output();
|
|
6899
|
+
init_rpc_registry();
|
|
6900
|
+
init_errors();
|
|
6901
|
+
var FAMILY_ORDER = [
|
|
6902
|
+
"system",
|
|
6903
|
+
"chain",
|
|
6904
|
+
"state",
|
|
6905
|
+
"author",
|
|
6906
|
+
"payment",
|
|
6907
|
+
"babe",
|
|
6908
|
+
"grandpa",
|
|
6909
|
+
"beefy",
|
|
6910
|
+
"mmr",
|
|
6911
|
+
"offchain",
|
|
6912
|
+
"dev",
|
|
6913
|
+
"spec",
|
|
6914
|
+
"chainHead",
|
|
6915
|
+
"chainSpec",
|
|
6916
|
+
"transaction",
|
|
6917
|
+
"archive",
|
|
6918
|
+
"other"
|
|
6919
|
+
];
|
|
6920
|
+
async function getMethodList(chainName, rpcUrl, refresh) {
|
|
6921
|
+
if (!refresh) {
|
|
6922
|
+
const cached = await loadRpcMethods(chainName);
|
|
6923
|
+
if (cached) {
|
|
6924
|
+
return { methods: cached.methods, version: cached.version, fromCache: true };
|
|
6925
|
+
}
|
|
6926
|
+
}
|
|
6927
|
+
const fresh = await fetchRpcMethods(rpcUrl);
|
|
6928
|
+
await saveRpcMethods(chainName, fresh.methods, fresh.version);
|
|
6929
|
+
return { methods: fresh.methods, version: fresh.version, fromCache: false };
|
|
6930
|
+
}
|
|
6931
|
+
function groupByFamily(methods) {
|
|
6932
|
+
const groups = new Map;
|
|
6933
|
+
for (const m of methods) {
|
|
6934
|
+
const family = RPC_REGISTRY[m]?.family ?? inferFamily(m);
|
|
6935
|
+
const list = groups.get(family) ?? [];
|
|
6936
|
+
list.push(m);
|
|
6937
|
+
groups.set(family, list);
|
|
6938
|
+
}
|
|
6939
|
+
for (const list of groups.values())
|
|
6940
|
+
list.sort();
|
|
6941
|
+
return groups;
|
|
6942
|
+
}
|
|
6943
|
+
function formatArgs(info) {
|
|
6944
|
+
if (info.args.length === 0)
|
|
6945
|
+
return "(no args)";
|
|
6946
|
+
return info.args.map((a) => `<${a.name}: ${a.type}${a.optional ? "?" : ""}>`).join(" ");
|
|
6947
|
+
}
|
|
6948
|
+
function printMethodHelp(method, info) {
|
|
6949
|
+
console.log();
|
|
6950
|
+
console.log(`${BOLD}${method}${RESET}`);
|
|
6951
|
+
if (info) {
|
|
6952
|
+
if (info.dangerous) {
|
|
6953
|
+
console.log(` ${YELLOW}⚠️ WRITE / state-changing${RESET}`);
|
|
6954
|
+
}
|
|
6955
|
+
if (info.subscription) {
|
|
6956
|
+
console.log(` ${DIM}subscription — not callable as a one-shot${RESET}`);
|
|
6957
|
+
}
|
|
6958
|
+
console.log(` ${info.description}`);
|
|
6959
|
+
console.log();
|
|
6960
|
+
console.log(` ${DIM}Family:${RESET} ${info.family}`);
|
|
6961
|
+
console.log(` ${DIM}Args:${RESET} ${formatArgs(info)}`);
|
|
6962
|
+
if (info.args.some((a) => a.description)) {
|
|
6963
|
+
console.log();
|
|
6964
|
+
for (const a of info.args) {
|
|
6965
|
+
if (a.description) {
|
|
6966
|
+
console.log(` ${CYAN}${a.name}${RESET} ${DIM}${a.description}${RESET}`);
|
|
6967
|
+
}
|
|
6968
|
+
}
|
|
6969
|
+
}
|
|
6970
|
+
} else {
|
|
6971
|
+
console.log(` ${DIM}No curated metadata. Args are passed through as raw JSON-RPC params.${RESET}`);
|
|
6972
|
+
console.log(` ${DIM}Family:${RESET} ${inferFamily(method)} (inferred)`);
|
|
6973
|
+
}
|
|
6974
|
+
console.log();
|
|
6975
|
+
}
|
|
6976
|
+
async function listMethods(chainName, rpcUrl, opts) {
|
|
6977
|
+
const { methods, version: version2, fromCache } = await getMethodList(chainName, rpcUrl, opts.refresh ?? false);
|
|
6978
|
+
if (isJsonOutput(opts)) {
|
|
6979
|
+
console.log(formatJson({
|
|
6980
|
+
chain: chainName,
|
|
6981
|
+
version: version2,
|
|
6982
|
+
fromCache,
|
|
6983
|
+
methods: methods.map((m) => {
|
|
6984
|
+
const info = RPC_REGISTRY[m];
|
|
6985
|
+
return {
|
|
6986
|
+
method: m,
|
|
6987
|
+
family: info?.family ?? inferFamily(m),
|
|
6988
|
+
description: info?.description,
|
|
6989
|
+
dangerous: info?.dangerous ?? false,
|
|
6990
|
+
subscription: info?.subscription ?? false
|
|
6991
|
+
};
|
|
6992
|
+
})
|
|
6993
|
+
}));
|
|
6994
|
+
return;
|
|
6995
|
+
}
|
|
6996
|
+
printHeading(`RPC methods on ${chainName} (${methods.length})`);
|
|
6997
|
+
const groups = groupByFamily(methods);
|
|
6998
|
+
for (const family of FAMILY_ORDER) {
|
|
6999
|
+
const list = groups.get(family);
|
|
7000
|
+
if (!list || list.length === 0)
|
|
7001
|
+
continue;
|
|
7002
|
+
console.log(`${BOLD}${family}${RESET} ${DIM}(${list.length})${RESET}`);
|
|
7003
|
+
for (const m of list) {
|
|
7004
|
+
const info = RPC_REGISTRY[m];
|
|
7005
|
+
const tags = [];
|
|
7006
|
+
if (info?.dangerous)
|
|
7007
|
+
tags.push(`${YELLOW}⚠ write${RESET}`);
|
|
7008
|
+
if (info?.subscription)
|
|
7009
|
+
tags.push(`${DIM}sub${RESET}`);
|
|
7010
|
+
const suffix = tags.length > 0 ? ` ${tags.join(" ")}` : "";
|
|
7011
|
+
const desc = info?.description ? ` ${DIM}${info.description}${RESET}` : "";
|
|
7012
|
+
console.log(` ${CYAN}${m}${RESET}${suffix}${desc}`);
|
|
7013
|
+
}
|
|
7014
|
+
console.log();
|
|
7015
|
+
}
|
|
7016
|
+
if (!fromCache) {
|
|
7017
|
+
console.log(`${DIM}(fetched from node — cached for next run)${RESET}`);
|
|
7018
|
+
}
|
|
7019
|
+
}
|
|
7020
|
+
async function handleRpc(method, args, opts) {
|
|
7021
|
+
const config = await loadConfig();
|
|
7022
|
+
const { name: chainName, chain: chainConfig } = resolveChain(config, opts.chain);
|
|
7023
|
+
const rpcUrl = opts.rpc ?? chainConfig.rpc;
|
|
7024
|
+
if (!rpcUrl) {
|
|
7025
|
+
throw new CliError(`No RPC endpoint for chain "${chainName}". Pass --rpc or run \`dot chain add ${chainName} --rpc <url>\`.`);
|
|
7026
|
+
}
|
|
7027
|
+
if (!method) {
|
|
7028
|
+
await listMethods(chainName, rpcUrl, opts);
|
|
7029
|
+
return;
|
|
7030
|
+
}
|
|
7031
|
+
const info = RPC_REGISTRY[method];
|
|
7032
|
+
if (opts.help) {
|
|
7033
|
+
printMethodHelp(method, info);
|
|
7034
|
+
return;
|
|
7035
|
+
}
|
|
7036
|
+
const { methods: knownMethods } = await getMethodList(chainName, rpcUrl, opts.refresh ?? false);
|
|
7037
|
+
if (!knownMethods.includes(method)) {
|
|
7038
|
+
const hint = suggestMessage("method", method, knownMethods);
|
|
7039
|
+
throw new CliError(`Method "${method}" is not exposed by the node for "${chainName}".${hint ? ` ${hint}` : ""} ` + `Run \`dot ${chainName}.rpc --refresh\` if the node has been upgraded.`);
|
|
7040
|
+
}
|
|
7041
|
+
if (info?.subscription) {
|
|
7042
|
+
throw new CliError(`"${method}" is a subscription method (requires a follow session) and is not callable as a one-shot. ` + `Use a long-running client for streaming RPC.`);
|
|
7043
|
+
}
|
|
7044
|
+
if (!info && /(_subscribe|_unsubscribe)/.test(method)) {
|
|
7045
|
+
throw new CliError(`"${method}" looks like a subscription/unsubscription method and isn't supported as a one-shot. ` + `Pass --help to see what we know about it.`);
|
|
7046
|
+
}
|
|
7047
|
+
if (info) {
|
|
7048
|
+
const required = info.args.filter((a) => !a.optional).length;
|
|
7049
|
+
if (args.length < required) {
|
|
7050
|
+
throw new CliError(`"${method}" expects at least ${required} argument(s) (${formatArgs(info)}); got ${args.length}.`);
|
|
7051
|
+
}
|
|
7052
|
+
}
|
|
7053
|
+
const params = args.map(parseValue);
|
|
7054
|
+
const result = await rpcRequest(rpcUrl, method, params);
|
|
7055
|
+
printResult(result, isJsonOutput(opts) ? "json" : opts.output);
|
|
7056
|
+
}
|
|
7057
|
+
|
|
5950
7058
|
// src/commands/sign.ts
|
|
5951
7059
|
init_accounts();
|
|
5952
7060
|
init_hash();
|
|
@@ -7946,7 +9054,8 @@ var CATEGORY_ALIASES = {
|
|
|
7946
9054
|
api: "apis",
|
|
7947
9055
|
extensions: "extensions",
|
|
7948
9056
|
extension: "extensions",
|
|
7949
|
-
ext: "extensions"
|
|
9057
|
+
ext: "extensions",
|
|
9058
|
+
rpc: "rpc"
|
|
7950
9059
|
};
|
|
7951
9060
|
function matchCategory(segment) {
|
|
7952
9061
|
return CATEGORY_ALIASES[segment.toLowerCase()];
|
|
@@ -7961,7 +9070,7 @@ function parseDotPath(input, knownChains = []) {
|
|
|
7961
9070
|
const cat = matchCategory(parts[0]);
|
|
7962
9071
|
if (cat)
|
|
7963
9072
|
return { category: cat };
|
|
7964
|
-
throw new Error(`Unknown command "${parts[0]}". Expected a category (query, tx, const, events, errors, apis, extensions) or a named command.`);
|
|
9073
|
+
throw new Error(`Unknown command "${parts[0]}". Expected a category (query, tx, const, events, errors, apis, extensions, rpc) or a named command.`);
|
|
7965
9074
|
}
|
|
7966
9075
|
case 2: {
|
|
7967
9076
|
const cat = matchCategory(parts[0]);
|
|
@@ -8043,6 +9152,7 @@ if (process.argv[2] === "__complete") {
|
|
|
8043
9152
|
console.log(" errors List or inspect pallet errors");
|
|
8044
9153
|
console.log(" apis Browse and call runtime APIs");
|
|
8045
9154
|
console.log(" extensions List transaction extensions on a chain");
|
|
9155
|
+
console.log(" rpc Call raw JSON-RPC methods on a node");
|
|
8046
9156
|
console.log();
|
|
8047
9157
|
console.log("Examples:");
|
|
8048
9158
|
console.log(" dot polkadot.query.System.Account <addr> Query a storage item");
|
|
@@ -8055,6 +9165,8 @@ if (process.argv[2] === "__complete") {
|
|
|
8055
9165
|
console.log(" dot metadata polkadot Dump runtime metadata as JSON");
|
|
8056
9166
|
console.log(" dot polkadot.extensions List transaction extensions");
|
|
8057
9167
|
console.log(" dot polkadot.extensions.CheckMortality Inspect one extension");
|
|
9168
|
+
console.log(" dot polkadot.rpc List RPC methods on the node");
|
|
9169
|
+
console.log(" dot polkadot.rpc.system_health Call a JSON-RPC method");
|
|
8058
9170
|
console.log(" dot query.System.Number --chain polkadot --chain flag form");
|
|
8059
9171
|
console.log(" dot ./transfer.yaml --from alice Run from file (chain in YAML)");
|
|
8060
9172
|
console.log(" dot tx.0x1f0003... --to-yaml --chain polkadot Decode hex call to YAML");
|
|
@@ -8068,7 +9180,7 @@ if (process.argv[2] === "__complete") {
|
|
|
8068
9180
|
console.log(" account Manage accounts");
|
|
8069
9181
|
console.log(" hash Hash utilities");
|
|
8070
9182
|
console.log(" sign Sign a message with an account keypair");
|
|
8071
|
-
console.log(" parachain Derive parachain sovereign accounts");
|
|
9183
|
+
console.log(" parachain Derive parachain sovereign accounts (deprecated \u2014 use `account inspect --parachain`)");
|
|
8072
9184
|
console.log(" verifiable Derive Bandersnatch member key from mnemonic");
|
|
8073
9185
|
console.log(" completions <sh> Generate shell completions (zsh, bash, fish)");
|
|
8074
9186
|
console.log();
|
|
@@ -8099,7 +9211,7 @@ if (process.argv[2] === "__complete") {
|
|
|
8099
9211
|
registerVerifiableCommands(cli);
|
|
8100
9212
|
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("--to-yaml", "Decode call to YAML file format (for tx)").option("--to-json", "Decode call to JSON file format (for tx)").option("--ext <json>", "Custom signed extension values as JSON (for tx)").option("--asset <json>", "Pay fees in an alternative asset (XCM location JSON, for tx)").option("-w, --wait <level>", "Resolve at: broadcast, best-block (or best), finalized (for tx)", {
|
|
8101
9213
|
default: "finalized"
|
|
8102
|
-
}).option("--dump", "Dump all entries of a storage map (without specifying a key)").option("--var <kv>", "Template variable for file input (KEY=VALUE, repeatable)").option("--nonce <n>", "Custom nonce for manual tx sequencing (for tx)").option("--tip <amount>", "Tip to prioritize transaction (for tx)").option("--mortality <spec>", '"immortal" or period number (for tx)').option("--at <block>", 'Block hash, "best", or "finalized" to validate against (for tx)').option("--unsigned", "Submit as unsigned/bare transaction (no signer required, for tx)").action(async (dotpath, args, opts) => {
|
|
9214
|
+
}).option("--dump", "Dump all entries of a storage map (without specifying a key)").option("--var <kv>", "Template variable for file input (KEY=VALUE, repeatable)").option("--nonce <n>", "Custom nonce for manual tx sequencing (for tx)").option("--tip <amount>", "Tip to prioritize transaction (for tx)").option("--mortality <spec>", '"immortal" or period number (for tx)').option("--at <block>", 'Block hash, "best", or "finalized" to validate against (for tx)').option("--unsigned", "Submit as unsigned/bare transaction (no signer required, for tx)").option("--refresh", "Refresh the cached RPC method list from the node (for rpc)").action(async (dotpath, args, opts) => {
|
|
8103
9215
|
if (!dotpath) {
|
|
8104
9216
|
printHelp();
|
|
8105
9217
|
return;
|
|
@@ -8162,9 +9274,10 @@ if (process.argv[2] === "__complete") {
|
|
|
8162
9274
|
} catch {
|
|
8163
9275
|
throw new CliError2(`Unknown command "${dotpath}". Run "dot --help" for available commands.`);
|
|
8164
9276
|
}
|
|
9277
|
+
const isFlatCategory = parsed.category === "rpc" || parsed.category === "extensions";
|
|
8165
9278
|
if (!parsed.pallet && args.length > 0) {
|
|
8166
9279
|
parsed.pallet = args.shift();
|
|
8167
|
-
if (!parsed.item && args.length > 0) {
|
|
9280
|
+
if (!isFlatCategory && !parsed.item && args.length > 0) {
|
|
8168
9281
|
parsed.item = args.shift();
|
|
8169
9282
|
}
|
|
8170
9283
|
}
|
|
@@ -8231,6 +9344,18 @@ if (process.argv[2] === "__complete") {
|
|
|
8231
9344
|
await handleExtensions(parsed.pallet, handlerOpts);
|
|
8232
9345
|
break;
|
|
8233
9346
|
}
|
|
9347
|
+
case "rpc": {
|
|
9348
|
+
if (parsed.item) {
|
|
9349
|
+
const suggestion = parsed.chain ? `dot ${parsed.chain}.rpc.${parsed.pallet}` : opts.chain ? `dot rpc.${parsed.pallet} --chain ${opts.chain}` : `dot rpc.${parsed.pallet} --chain <chain>`;
|
|
9350
|
+
throw new CliError2(`RPC methods have no sub-items. Try "${suggestion}".`);
|
|
9351
|
+
}
|
|
9352
|
+
await handleRpc(parsed.pallet, args, {
|
|
9353
|
+
...handlerOpts,
|
|
9354
|
+
help: cli.options.help,
|
|
9355
|
+
refresh: opts.refresh
|
|
9356
|
+
});
|
|
9357
|
+
break;
|
|
9358
|
+
}
|
|
8234
9359
|
}
|
|
8235
9360
|
});
|
|
8236
9361
|
cli.option("--help, -h", "Display this message");
|