polkadot-cli 1.1.1 → 1.2.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 +34 -0
- package/dist/cli.mjs +130 -37
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -79,6 +79,10 @@ dot accounts # shorthand, same as above
|
|
|
79
79
|
# List all accounts (dev + stored)
|
|
80
80
|
dot account list
|
|
81
81
|
|
|
82
|
+
# Add a watch-only address (no secret — for use as tx recipient or query target)
|
|
83
|
+
dot account add treasury 5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY
|
|
84
|
+
dot account add council 0xd43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d
|
|
85
|
+
|
|
82
86
|
# Create a new account (generates a mnemonic)
|
|
83
87
|
dot account create my-validator
|
|
84
88
|
|
|
@@ -113,6 +117,36 @@ dot account inspect alice --prefix 0 # Polkadot mainnet prefix
|
|
|
113
117
|
dot account inspect alice --output json # JSON output
|
|
114
118
|
```
|
|
115
119
|
|
|
120
|
+
#### Watch-only accounts
|
|
121
|
+
|
|
122
|
+
Add named addresses without secrets — useful for saving frequently-used recipients, multisig members, or query targets:
|
|
123
|
+
|
|
124
|
+
```bash
|
|
125
|
+
dot account add treasury 5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY
|
|
126
|
+
dot account add council 0xd43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
Watch-only accounts appear in `dot account list` with a `(watch-only)` badge and can be inspected and removed like any other account. They cannot be used with `--from` (signing) or as a source for `derive`.
|
|
130
|
+
|
|
131
|
+
The `add` subcommand is context-sensitive: bare `add <name> <address>` creates a watch-only entry, while `add --secret` or `add --env` imports a keyed account (same as `import`).
|
|
132
|
+
|
|
133
|
+
#### Named address resolution
|
|
134
|
+
|
|
135
|
+
Named accounts (both watch-only and keyed) resolve automatically everywhere an AccountId32 or MultiAddress is expected — in `dot tx` arguments and `dot query` keys:
|
|
136
|
+
|
|
137
|
+
```bash
|
|
138
|
+
# Use a named account as transfer recipient
|
|
139
|
+
dot tx Balances.transferKeepAlive treasury 1000000000000 --from alice
|
|
140
|
+
|
|
141
|
+
# Query by account name
|
|
142
|
+
dot query System.Account treasury
|
|
143
|
+
|
|
144
|
+
# Dev accounts also resolve
|
|
145
|
+
dot tx Balances.transferKeepAlive bob 1000000000000 --from alice
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
Resolution order: dev account name > stored account name > SS58 address > hex public key. If the input doesn't match any, the CLI shows an error listing available account names.
|
|
149
|
+
|
|
116
150
|
#### Inspect accounts
|
|
117
151
|
|
|
118
152
|
Convert between SS58 addresses, hex public keys, and account names. Accepts any of:
|
package/dist/cli.mjs
CHANGED
|
@@ -5,7 +5,7 @@ var __require = /* @__PURE__ */ createRequire(import.meta.url);
|
|
|
5
5
|
// src/cli.ts
|
|
6
6
|
import cac from "cac";
|
|
7
7
|
// package.json
|
|
8
|
-
var version = "1.
|
|
8
|
+
var version = "1.2.0";
|
|
9
9
|
|
|
10
10
|
// src/config/accounts-store.ts
|
|
11
11
|
import { access as access2, mkdir as mkdir2, readFile as readFile2, writeFile as writeFile2 } from "node:fs/promises";
|
|
@@ -238,6 +238,9 @@ function findAccount(file, name) {
|
|
|
238
238
|
function isEnvSecret(secret) {
|
|
239
239
|
return typeof secret === "object" && secret !== null && "env" in secret;
|
|
240
240
|
}
|
|
241
|
+
function isWatchOnly(account) {
|
|
242
|
+
return account.secret === undefined;
|
|
243
|
+
}
|
|
241
244
|
|
|
242
245
|
// src/core/accounts.ts
|
|
243
246
|
import { sr25519CreateDerive } from "@polkadot-labs/hdkd";
|
|
@@ -354,6 +357,9 @@ async function resolveAccountSigner(name) {
|
|
|
354
357
|
const available = [...DEV_NAMES, ...accountsFile.accounts.map((a) => a.name)];
|
|
355
358
|
throw new Error(`Unknown account "${name}". Available accounts: ${available.join(", ")}`);
|
|
356
359
|
}
|
|
360
|
+
if (account.secret === undefined) {
|
|
361
|
+
throw new Error(`Account "${name}" is watch-only (no secret). Cannot sign. Import with --secret or --env.`);
|
|
362
|
+
}
|
|
357
363
|
const secret = resolveSecret(account.secret);
|
|
358
364
|
const isHexSeed = /^0x[0-9a-fA-F]{64}$/.test(secret);
|
|
359
365
|
const keypair = isHexSeed ? deriveFromHexSeed(secret, account.derivationPath) : deriveFromMnemonic(secret, account.derivationPath);
|
|
@@ -463,15 +469,19 @@ function firstSentence(docs) {
|
|
|
463
469
|
// src/commands/account.ts
|
|
464
470
|
var ACCOUNT_HELP = `
|
|
465
471
|
${BOLD}Usage:${RESET}
|
|
472
|
+
$ dot account add <name> <ss58|hex> Add a watch-only address (no secret)
|
|
473
|
+
$ dot account add <name> --secret <s> [--path <derivation>] Import from BIP39 mnemonic
|
|
474
|
+
$ dot account add <name> --env <VAR> [--path <derivation>] Import account backed by env variable
|
|
466
475
|
$ dot account create|new <name> [--path <derivation>] Create a new account
|
|
467
|
-
$ dot account import
|
|
468
|
-
$ dot account import
|
|
476
|
+
$ dot account import <name> --secret <s> [--path <derivation>] Import from BIP39 mnemonic
|
|
477
|
+
$ dot account import <name> --env <VAR> [--path <derivation>] Import account backed by env variable
|
|
469
478
|
$ dot account derive <source> <new-name> --path <derivation> Derive a child account
|
|
470
479
|
$ dot account inspect <input> [--prefix <N>] Inspect an account/address/key
|
|
471
480
|
$ dot account list List all accounts
|
|
472
481
|
$ dot account remove|delete <name> [name2] ... Remove stored account(s)
|
|
473
482
|
|
|
474
483
|
${BOLD}Examples:${RESET}
|
|
484
|
+
$ dot account add treasury 5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY
|
|
475
485
|
$ dot account create my-validator
|
|
476
486
|
$ dot account create my-staking --path //staking
|
|
477
487
|
$ dot account create multi --path //polkadot//0/wallet
|
|
@@ -500,8 +510,11 @@ function registerAccountCommands(cli) {
|
|
|
500
510
|
case "new":
|
|
501
511
|
case "create":
|
|
502
512
|
return accountCreate(names[0], opts);
|
|
503
|
-
case "import":
|
|
504
513
|
case "add":
|
|
514
|
+
if (opts.secret || opts.env)
|
|
515
|
+
return accountImport(names[0], opts);
|
|
516
|
+
return accountAddWatchOnly(names[0], names[1]);
|
|
517
|
+
case "import":
|
|
505
518
|
return accountImport(names[0], opts);
|
|
506
519
|
case "derive":
|
|
507
520
|
return accountDerive(names[0], names[1], opts);
|
|
@@ -618,6 +631,48 @@ async function accountImport(name, opts) {
|
|
|
618
631
|
console.log();
|
|
619
632
|
}
|
|
620
633
|
}
|
|
634
|
+
async function accountAddWatchOnly(name, address) {
|
|
635
|
+
if (!name) {
|
|
636
|
+
console.error(`Account name is required.
|
|
637
|
+
`);
|
|
638
|
+
console.error("Usage: dot account add <name> <ss58-address|0x-public-key>");
|
|
639
|
+
process.exit(1);
|
|
640
|
+
}
|
|
641
|
+
if (!address) {
|
|
642
|
+
console.error(`Address is required.
|
|
643
|
+
`);
|
|
644
|
+
console.error("Usage: dot account add <name> <ss58-address|0x-public-key>");
|
|
645
|
+
process.exit(1);
|
|
646
|
+
}
|
|
647
|
+
if (isDevAccount(name)) {
|
|
648
|
+
throw new Error(`"${name}" is a built-in dev account and cannot be used as a custom account name.`);
|
|
649
|
+
}
|
|
650
|
+
const accountsFile = await loadAccounts();
|
|
651
|
+
if (findAccount(accountsFile, name)) {
|
|
652
|
+
throw new Error(`Account "${name}" already exists.`);
|
|
653
|
+
}
|
|
654
|
+
let hexPub;
|
|
655
|
+
if (isHexPublicKey(address)) {
|
|
656
|
+
hexPub = address;
|
|
657
|
+
} else {
|
|
658
|
+
try {
|
|
659
|
+
const decoded = fromSs58(address);
|
|
660
|
+
hexPub = publicKeyToHex(decoded);
|
|
661
|
+
} catch {
|
|
662
|
+
throw new Error(`Invalid address "${address}". Expected an SS58 address or 0x-prefixed 32-byte hex public key.`);
|
|
663
|
+
}
|
|
664
|
+
}
|
|
665
|
+
accountsFile.accounts.push({
|
|
666
|
+
name,
|
|
667
|
+
publicKey: hexPub,
|
|
668
|
+
derivationPath: ""
|
|
669
|
+
});
|
|
670
|
+
await saveAccounts(accountsFile);
|
|
671
|
+
printHeading("Account Added (watch-only)");
|
|
672
|
+
console.log(` ${BOLD}Name:${RESET} ${name}`);
|
|
673
|
+
console.log(` ${BOLD}Address:${RESET} ${toSs58(hexPub)}`);
|
|
674
|
+
console.log();
|
|
675
|
+
}
|
|
621
676
|
async function accountDerive(sourceName, newName, opts) {
|
|
622
677
|
if (!sourceName) {
|
|
623
678
|
console.error(`Source account name is required.
|
|
@@ -645,15 +700,19 @@ async function accountDerive(sourceName, newName, opts) {
|
|
|
645
700
|
if (!source) {
|
|
646
701
|
throw new Error(`Source account "${sourceName}" not found.`);
|
|
647
702
|
}
|
|
703
|
+
if (isWatchOnly(source)) {
|
|
704
|
+
throw new Error(`Cannot derive from "${sourceName}": watch-only, no secret.`);
|
|
705
|
+
}
|
|
648
706
|
if (findAccount(accountsFile, newName)) {
|
|
649
707
|
throw new Error(`Account "${newName}" already exists.`);
|
|
650
708
|
}
|
|
651
709
|
const path = opts.path;
|
|
652
|
-
|
|
653
|
-
|
|
710
|
+
const sourceSecret = source.secret;
|
|
711
|
+
if (isEnvSecret(sourceSecret)) {
|
|
712
|
+
const publicKey = tryDerivePublicKey(sourceSecret.env, path) ?? "";
|
|
654
713
|
accountsFile.accounts.push({
|
|
655
714
|
name: newName,
|
|
656
|
-
secret:
|
|
715
|
+
secret: sourceSecret,
|
|
657
716
|
publicKey,
|
|
658
717
|
derivationPath: path
|
|
659
718
|
});
|
|
@@ -662,20 +721,20 @@ async function accountDerive(sourceName, newName, opts) {
|
|
|
662
721
|
console.log(` ${BOLD}Name:${RESET} ${newName}`);
|
|
663
722
|
console.log(` ${BOLD}Source:${RESET} ${sourceName}`);
|
|
664
723
|
console.log(` ${BOLD}Path:${RESET} ${path}`);
|
|
665
|
-
console.log(` ${BOLD}Env:${RESET} ${
|
|
724
|
+
console.log(` ${BOLD}Env:${RESET} ${sourceSecret.env}`);
|
|
666
725
|
if (publicKey) {
|
|
667
726
|
console.log(` ${BOLD}Address:${RESET} ${toSs58(publicKey)}`);
|
|
668
727
|
} else {
|
|
669
|
-
console.log(` ${YELLOW}Address will resolve when $${
|
|
728
|
+
console.log(` ${YELLOW}Address will resolve when $${sourceSecret.env} is set.${RESET}`);
|
|
670
729
|
}
|
|
671
730
|
console.log();
|
|
672
731
|
} else {
|
|
673
|
-
const { publicKey } = importAccount(
|
|
732
|
+
const { publicKey } = importAccount(sourceSecret, path);
|
|
674
733
|
const hexPub = publicKeyToHex(publicKey);
|
|
675
734
|
const address = toSs58(publicKey);
|
|
676
735
|
accountsFile.accounts.push({
|
|
677
736
|
name: newName,
|
|
678
|
-
secret:
|
|
737
|
+
secret: sourceSecret,
|
|
679
738
|
publicKey: hexPub,
|
|
680
739
|
derivationPath: path
|
|
681
740
|
});
|
|
@@ -704,7 +763,10 @@ async function accountList() {
|
|
|
704
763
|
displayName += ` (${account.derivationPath})`;
|
|
705
764
|
}
|
|
706
765
|
let address;
|
|
707
|
-
if (
|
|
766
|
+
if (isWatchOnly(account)) {
|
|
767
|
+
displayName += " (watch-only)";
|
|
768
|
+
address = account.publicKey ? toSs58(account.publicKey) : "n/a";
|
|
769
|
+
} else if (account.secret !== undefined && isEnvSecret(account.secret)) {
|
|
708
770
|
displayName += ` (env: ${account.secret.env})`;
|
|
709
771
|
let pubKey = account.publicKey;
|
|
710
772
|
if (!pubKey) {
|
|
@@ -786,7 +848,7 @@ async function accountInspect(input, opts) {
|
|
|
786
848
|
name = account.name;
|
|
787
849
|
if (account.publicKey) {
|
|
788
850
|
publicKeyHex = account.publicKey;
|
|
789
|
-
} else if (isEnvSecret(account.secret)) {
|
|
851
|
+
} else if (account.secret !== undefined && isEnvSecret(account.secret)) {
|
|
790
852
|
const derived = tryDerivePublicKey(account.secret.env, account.derivationPath);
|
|
791
853
|
if (!derived) {
|
|
792
854
|
console.error(`Cannot derive public key for "${account.name}": $${account.secret.env} is not set.`);
|
|
@@ -2564,8 +2626,35 @@ import { Binary as Binary2 } from "polkadot-api";
|
|
|
2564
2626
|
var pjsAppsLink = (rpc, hash) => `https://polkadot.js.org/apps/?rpc=${encodeURIComponent(rpc)}#/explorer/query/${hash}`;
|
|
2565
2627
|
var papiLink = (rpc, hash) => `https://dev.papi.how/explorer/${hash}#networkId=custom&endpoint=${encodeURIComponent(rpc)}`;
|
|
2566
2628
|
|
|
2629
|
+
// src/core/resolve-address.ts
|
|
2630
|
+
async function resolveAccountAddress(input) {
|
|
2631
|
+
if (isDevAccount(input)) {
|
|
2632
|
+
return getDevAddress(input);
|
|
2633
|
+
}
|
|
2634
|
+
const accountsFile = await loadAccounts();
|
|
2635
|
+
const account = findAccount(accountsFile, input);
|
|
2636
|
+
if (account) {
|
|
2637
|
+
if (account.publicKey) {
|
|
2638
|
+
return toSs58(account.publicKey);
|
|
2639
|
+
}
|
|
2640
|
+
throw new Error(`Account "${account.name}" has no public key resolved yet.`);
|
|
2641
|
+
}
|
|
2642
|
+
try {
|
|
2643
|
+
const decoded = fromSs58(input);
|
|
2644
|
+
publicKeyToHex(decoded);
|
|
2645
|
+
return input;
|
|
2646
|
+
} catch {}
|
|
2647
|
+
if (isHexPublicKey(input)) {
|
|
2648
|
+
return input;
|
|
2649
|
+
}
|
|
2650
|
+
const stored = accountsFile.accounts.map((a) => a.name);
|
|
2651
|
+
const available = [...DEV_NAMES, ...stored];
|
|
2652
|
+
throw new Error(`Unknown account or address "${input}".
|
|
2653
|
+
Available accounts: ${available.join(", ")}`);
|
|
2654
|
+
}
|
|
2655
|
+
|
|
2567
2656
|
// src/commands/tx.ts
|
|
2568
|
-
function parseStructArgs(meta, fields, args, callLabel) {
|
|
2657
|
+
async function parseStructArgs(meta, fields, args, callLabel) {
|
|
2569
2658
|
const fieldNames = Object.keys(fields);
|
|
2570
2659
|
if (args.length !== fieldNames.length) {
|
|
2571
2660
|
const expected = fieldNames.map((name) => `${name}: ${describeType(meta.lookup, fields[name].id)}`).join(", ");
|
|
@@ -2577,7 +2666,7 @@ function parseStructArgs(meta, fields, args, callLabel) {
|
|
|
2577
2666
|
const name = fieldNames[i];
|
|
2578
2667
|
const entry = fields[name];
|
|
2579
2668
|
try {
|
|
2580
|
-
result[name] = parseTypedArg(meta, entry, args[i]);
|
|
2669
|
+
result[name] = await parseTypedArg(meta, entry, args[i]);
|
|
2581
2670
|
} catch (err) {
|
|
2582
2671
|
const typeDesc = describeType(meta.lookup, entry.id);
|
|
2583
2672
|
throw new Error(`Invalid value for argument '${name}' (expected ${typeDesc}): ${JSON.stringify(args[i])}
|
|
@@ -2723,7 +2812,7 @@ function parseEnumShorthand(arg) {
|
|
|
2723
2812
|
return null;
|
|
2724
2813
|
return { variant, inner: arg.slice(firstParen + 1, -1) };
|
|
2725
2814
|
}
|
|
2726
|
-
function parseTypedArg(meta, entry, arg) {
|
|
2815
|
+
async function parseTypedArg(meta, entry, arg) {
|
|
2727
2816
|
if (entry.type === "lookupEntry")
|
|
2728
2817
|
return parseTypedArg(meta, entry.value, arg);
|
|
2729
2818
|
switch (entry.type) {
|
|
@@ -2732,6 +2821,7 @@ function parseTypedArg(meta, entry, arg) {
|
|
|
2732
2821
|
case "compact":
|
|
2733
2822
|
return entry.isBig ? BigInt(arg) : parseInt(arg, 10);
|
|
2734
2823
|
case "AccountId32":
|
|
2824
|
+
return resolveAccountAddress(arg);
|
|
2735
2825
|
case "AccountId20":
|
|
2736
2826
|
return arg;
|
|
2737
2827
|
case "option": {
|
|
@@ -2760,7 +2850,7 @@ function parseTypedArg(meta, entry, arg) {
|
|
|
2760
2850
|
if (resolvedDef.type === "void" || shorthand.inner === "") {
|
|
2761
2851
|
return { type: matched2 };
|
|
2762
2852
|
}
|
|
2763
|
-
const innerValue = parseTypedArg(meta, variantDef, shorthand.inner);
|
|
2853
|
+
const innerValue = await parseTypedArg(meta, variantDef, shorthand.inner);
|
|
2764
2854
|
return normalizeValue(meta.lookup, entry, { type: matched2, value: innerValue });
|
|
2765
2855
|
}
|
|
2766
2856
|
}
|
|
@@ -2768,7 +2858,8 @@ function parseTypedArg(meta, entry, arg) {
|
|
|
2768
2858
|
const idVariant = entry.value.Id;
|
|
2769
2859
|
const innerType = idVariant.type === "lookupEntry" ? idVariant.value : idVariant;
|
|
2770
2860
|
if (innerType.type === "AccountId32" && !arg.startsWith("{")) {
|
|
2771
|
-
|
|
2861
|
+
const resolved = await resolveAccountAddress(arg);
|
|
2862
|
+
return { type: "Id", value: resolved };
|
|
2772
2863
|
}
|
|
2773
2864
|
}
|
|
2774
2865
|
const matched = variants.find((v) => v.toLowerCase() === arg.toLowerCase());
|
|
@@ -2919,7 +3010,7 @@ async function handleQuery(target, keys, opts) {
|
|
|
2919
3010
|
}
|
|
2920
3011
|
const unsafeApi = clientHandle.client.getUnsafeApi();
|
|
2921
3012
|
const storageApi = unsafeApi.query[palletInfo.name][storageItem.name];
|
|
2922
|
-
const parsedKeys = parseStorageKeys(meta, palletInfo.name, storageItem, keys);
|
|
3013
|
+
const parsedKeys = await parseStorageKeys(meta, palletInfo.name, storageItem, keys);
|
|
2923
3014
|
const format = opts.output ?? "pretty";
|
|
2924
3015
|
if (storageItem.type === "map" && parsedKeys.length === 0) {
|
|
2925
3016
|
const entries = await storageApi.getEntries();
|
|
@@ -2945,7 +3036,7 @@ ${DIM}Showing ${limit} of ${entries.length} entries. Use --limit 0 for all.${RES
|
|
|
2945
3036
|
function palletName(name) {
|
|
2946
3037
|
return name;
|
|
2947
3038
|
}
|
|
2948
|
-
function parseStorageKeys(meta, palletName2, storageItem, args) {
|
|
3039
|
+
async function parseStorageKeys(meta, palletName2, storageItem, args) {
|
|
2949
3040
|
if (storageItem.type === "plain" || storageItem.keyTypeId == null) {
|
|
2950
3041
|
return args.map(parseValue);
|
|
2951
3042
|
}
|
|
@@ -2956,11 +3047,11 @@ function parseStorageKeys(meta, palletName2, storageItem, args) {
|
|
|
2956
3047
|
const keyEntry = meta.lookup(storageItem.keyTypeId);
|
|
2957
3048
|
if (len === 1) {
|
|
2958
3049
|
if (args.length === 1) {
|
|
2959
|
-
return [parseTypedArg(meta, keyEntry, args[0])];
|
|
3050
|
+
return [await parseTypedArg(meta, keyEntry, args[0])];
|
|
2960
3051
|
}
|
|
2961
3052
|
if (keyEntry.type === "struct") {
|
|
2962
3053
|
const label = `${palletName2}.${storageItem.name} key`;
|
|
2963
|
-
return [parseStructArgs(meta, keyEntry.value, args, label)];
|
|
3054
|
+
return [await parseStructArgs(meta, keyEntry.value, args, label)];
|
|
2964
3055
|
}
|
|
2965
3056
|
const typeDesc = describeType(meta.lookup, storageItem.keyTypeId);
|
|
2966
3057
|
throw new Error(`${palletName2}.${storageItem.name} key expects ${typeDesc}
|
|
@@ -2977,9 +3068,9 @@ function parseStorageKeys(meta, palletName2, storageItem, args) {
|
|
|
2977
3068
|
}
|
|
2978
3069
|
if (keyEntry.type === "tuple") {
|
|
2979
3070
|
const entries = keyEntry.value;
|
|
2980
|
-
return entries.map((entry, i) => parseTypedArg(meta, entry, args[i]));
|
|
3071
|
+
return Promise.all(entries.map((entry, i) => parseTypedArg(meta, entry, args[i])));
|
|
2981
3072
|
}
|
|
2982
|
-
return args.map((arg) => parseTypedArg(meta, keyEntry, arg));
|
|
3073
|
+
return Promise.all(args.map((arg) => parseTypedArg(meta, keyEntry, arg)));
|
|
2983
3074
|
}
|
|
2984
3075
|
|
|
2985
3076
|
// src/commands/tx.ts
|
|
@@ -3090,7 +3181,7 @@ async function handleTx(target, args, opts) {
|
|
|
3090
3181
|
const callNames = palletInfo.calls.map((c) => c.name);
|
|
3091
3182
|
throw new Error(suggestMessage(`call in ${palletInfo.name}`, callName, callNames));
|
|
3092
3183
|
}
|
|
3093
|
-
const callData = parseCallArgs(meta, palletInfo.name, callInfo.name, args);
|
|
3184
|
+
const callData = await parseCallArgs(meta, palletInfo.name, callInfo.name, args);
|
|
3094
3185
|
if (opts.encode) {
|
|
3095
3186
|
const { codec, location } = meta.builder.buildCall(palletInfo.name, callInfo.name);
|
|
3096
3187
|
const encodedArgs = codec.enc(callData);
|
|
@@ -3339,7 +3430,7 @@ function formatEventValue(v) {
|
|
|
3339
3430
|
}
|
|
3340
3431
|
return JSON.stringify(v, (_k, val) => typeof val === "bigint" ? val.toString() : val);
|
|
3341
3432
|
}
|
|
3342
|
-
function parseCallArgs(meta, palletName2, callName, args) {
|
|
3433
|
+
async function parseCallArgs(meta, palletName2, callName, args) {
|
|
3343
3434
|
const palletMeta = meta.unified.pallets.find((p) => p.name === palletName2);
|
|
3344
3435
|
if (!palletMeta?.calls)
|
|
3345
3436
|
return;
|
|
@@ -3356,12 +3447,12 @@ function parseCallArgs(meta, palletName2, callName, args) {
|
|
|
3356
3447
|
return;
|
|
3357
3448
|
}
|
|
3358
3449
|
if (variant.type === "struct") {
|
|
3359
|
-
return parseStructArgs2(meta, variant.value, args, `${palletName2}.${callName}`);
|
|
3450
|
+
return await parseStructArgs2(meta, variant.value, args, `${palletName2}.${callName}`);
|
|
3360
3451
|
}
|
|
3361
3452
|
if (variant.type === "lookupEntry") {
|
|
3362
3453
|
const inner = variant.value;
|
|
3363
3454
|
if (inner.type === "struct") {
|
|
3364
|
-
return parseStructArgs2(meta, inner.value, args, `${palletName2}.${callName}`);
|
|
3455
|
+
return await parseStructArgs2(meta, inner.value, args, `${palletName2}.${callName}`);
|
|
3365
3456
|
}
|
|
3366
3457
|
if (inner.type === "void")
|
|
3367
3458
|
return;
|
|
@@ -3369,7 +3460,7 @@ function parseCallArgs(meta, palletName2, callName, args) {
|
|
|
3369
3460
|
throw new Error(`${palletName2}.${callName} takes 1 argument (${describeType(meta.lookup, inner.id)}), but ${args.length} provided.`);
|
|
3370
3461
|
}
|
|
3371
3462
|
try {
|
|
3372
|
-
return parseTypedArg2(meta, inner, args[0]);
|
|
3463
|
+
return await parseTypedArg2(meta, inner, args[0]);
|
|
3373
3464
|
} catch (err) {
|
|
3374
3465
|
const typeDesc = describeType(meta.lookup, inner.id);
|
|
3375
3466
|
throw new Error(`Invalid value for argument 0 (expected ${typeDesc}): ${JSON.stringify(args[0])}`, { cause: err });
|
|
@@ -3380,18 +3471,18 @@ function parseCallArgs(meta, palletName2, callName, args) {
|
|
|
3380
3471
|
if (args.length !== entries.length) {
|
|
3381
3472
|
throw new Error(`${palletName2}.${callName} takes ${entries.length} arguments, but ${args.length} provided.`);
|
|
3382
3473
|
}
|
|
3383
|
-
return entries.map((entry, i) => {
|
|
3474
|
+
return Promise.all(entries.map(async (entry, i) => {
|
|
3384
3475
|
try {
|
|
3385
|
-
return parseTypedArg2(meta, entry, args[i]);
|
|
3476
|
+
return await parseTypedArg2(meta, entry, args[i]);
|
|
3386
3477
|
} catch (err) {
|
|
3387
3478
|
const typeDesc = describeType(meta.lookup, entry.id);
|
|
3388
3479
|
throw new Error(`Invalid value for argument ${i} (expected ${typeDesc}): ${JSON.stringify(args[i])}`, { cause: err });
|
|
3389
3480
|
}
|
|
3390
|
-
});
|
|
3481
|
+
}));
|
|
3391
3482
|
}
|
|
3392
3483
|
return args.length === 0 ? undefined : args.map(parseValue);
|
|
3393
3484
|
}
|
|
3394
|
-
function parseStructArgs2(meta, fields, args, callLabel) {
|
|
3485
|
+
async function parseStructArgs2(meta, fields, args, callLabel) {
|
|
3395
3486
|
const fieldNames = Object.keys(fields);
|
|
3396
3487
|
if (args.length !== fieldNames.length) {
|
|
3397
3488
|
const expected = fieldNames.map((name) => `${name}: ${describeType(meta.lookup, fields[name].id)}`).join(", ");
|
|
@@ -3403,7 +3494,7 @@ function parseStructArgs2(meta, fields, args, callLabel) {
|
|
|
3403
3494
|
const name = fieldNames[i];
|
|
3404
3495
|
const entry = fields[name];
|
|
3405
3496
|
try {
|
|
3406
|
-
result[name] = parseTypedArg2(meta, entry, args[i]);
|
|
3497
|
+
result[name] = await parseTypedArg2(meta, entry, args[i]);
|
|
3407
3498
|
} catch (err) {
|
|
3408
3499
|
const typeDesc = describeType(meta.lookup, entry.id);
|
|
3409
3500
|
throw new Error(`Invalid value for argument '${name}' (expected ${typeDesc}): ${JSON.stringify(args[i])}
|
|
@@ -3549,7 +3640,7 @@ function parseEnumShorthand2(arg) {
|
|
|
3549
3640
|
return null;
|
|
3550
3641
|
return { variant, inner: arg.slice(firstParen + 1, -1) };
|
|
3551
3642
|
}
|
|
3552
|
-
function parseTypedArg2(meta, entry, arg) {
|
|
3643
|
+
async function parseTypedArg2(meta, entry, arg) {
|
|
3553
3644
|
if (entry.type === "lookupEntry")
|
|
3554
3645
|
return parseTypedArg2(meta, entry.value, arg);
|
|
3555
3646
|
switch (entry.type) {
|
|
@@ -3558,6 +3649,7 @@ function parseTypedArg2(meta, entry, arg) {
|
|
|
3558
3649
|
case "compact":
|
|
3559
3650
|
return entry.isBig ? BigInt(arg) : parseInt(arg, 10);
|
|
3560
3651
|
case "AccountId32":
|
|
3652
|
+
return resolveAccountAddress(arg);
|
|
3561
3653
|
case "AccountId20":
|
|
3562
3654
|
return arg;
|
|
3563
3655
|
case "option": {
|
|
@@ -3586,7 +3678,7 @@ function parseTypedArg2(meta, entry, arg) {
|
|
|
3586
3678
|
if (resolvedDef.type === "void" || shorthand.inner === "") {
|
|
3587
3679
|
return { type: matched2 };
|
|
3588
3680
|
}
|
|
3589
|
-
const innerValue = parseTypedArg2(meta, variantDef, shorthand.inner);
|
|
3681
|
+
const innerValue = await parseTypedArg2(meta, variantDef, shorthand.inner);
|
|
3590
3682
|
return normalizeValue2(meta.lookup, entry, { type: matched2, value: innerValue });
|
|
3591
3683
|
}
|
|
3592
3684
|
}
|
|
@@ -3594,7 +3686,8 @@ function parseTypedArg2(meta, entry, arg) {
|
|
|
3594
3686
|
const idVariant = entry.value.Id;
|
|
3595
3687
|
const innerType = idVariant.type === "lookupEntry" ? idVariant.value : idVariant;
|
|
3596
3688
|
if (innerType.type === "AccountId32" && !arg.startsWith("{")) {
|
|
3597
|
-
|
|
3689
|
+
const resolved = await resolveAccountAddress(arg);
|
|
3690
|
+
return { type: "Id", value: resolved };
|
|
3598
3691
|
}
|
|
3599
3692
|
}
|
|
3600
3693
|
const matched = variants.find((v) => v.toLowerCase() === arg.toLowerCase());
|