polkadot-cli 0.8.1 → 0.10.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 +52 -1
- package/dist/cli.mjs +164 -22
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -42,7 +42,7 @@ dot chain remove westend
|
|
|
42
42
|
|
|
43
43
|
Dev accounts (Alice, Bob, Charlie, Dave, Eve, Ferdie) are always available for testnets. Create or import your own accounts for any chain.
|
|
44
44
|
|
|
45
|
-
> **Security warning:** Account secrets (mnemonics and seeds) are currently stored **unencrypted** in `~/.polkadot/accounts.json`. Do not use this for high-value accounts on mainnet. Encrypted storage is planned for a future release.
|
|
45
|
+
> **Security warning:** Account secrets (mnemonics and seeds) are currently stored **unencrypted** in `~/.polkadot/accounts.json`. Do not use this for high-value accounts on mainnet. Encrypted storage is planned for a future release. Use `--env` to keep secrets off disk entirely.
|
|
46
46
|
|
|
47
47
|
```bash
|
|
48
48
|
# List all accounts (dev + stored)
|
|
@@ -55,10 +55,26 @@ dot account create my-validator
|
|
|
55
55
|
# Import from a BIP39 mnemonic
|
|
56
56
|
dot account import treasury --secret "word1 word2 ... word12"
|
|
57
57
|
|
|
58
|
+
# Add an env-var-backed account (secret stays off disk)
|
|
59
|
+
dot account add ci-signer --env MY_SECRET
|
|
60
|
+
|
|
61
|
+
# Use it — the env var is read at signing time
|
|
62
|
+
MY_SECRET="word1 word2 ..." dot tx System.remark 0xdead --from ci-signer
|
|
63
|
+
|
|
58
64
|
# Remove an account
|
|
59
65
|
dot account remove my-validator
|
|
60
66
|
```
|
|
61
67
|
|
|
68
|
+
#### Env-var-backed accounts
|
|
69
|
+
|
|
70
|
+
For CI/CD and security-conscious workflows, store a reference to an environment variable instead of the secret itself:
|
|
71
|
+
|
|
72
|
+
```bash
|
|
73
|
+
dot account add ci-signer --env MY_SECRET
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
The secret is never written to disk. At signing time, the CLI reads `$MY_SECRET` and derives the keypair. If the variable is not set, the CLI errors with a clear message. `account list` shows an `(env: MY_SECRET)` badge and resolves the address live when the variable is available.
|
|
77
|
+
|
|
62
78
|
**Supported secret formats for import:**
|
|
63
79
|
|
|
64
80
|
| Format | Example | Status |
|
|
@@ -102,6 +118,20 @@ dot query System.Number --output json | jq '.+1'
|
|
|
102
118
|
dot query kusama.System.Account 5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY
|
|
103
119
|
```
|
|
104
120
|
|
|
121
|
+
#### Output formatting
|
|
122
|
+
|
|
123
|
+
Query results automatically convert on-chain types for readability:
|
|
124
|
+
|
|
125
|
+
- **BigInt** values (e.g. balances) render as decimal strings
|
|
126
|
+
- **Binary** fields (e.g. token `name`, `symbol`) render as text when valid UTF-8, or as `0x`-prefixed hex otherwise
|
|
127
|
+
- **Uint8Array** values render as `0x`-prefixed hex
|
|
128
|
+
|
|
129
|
+
```bash
|
|
130
|
+
# Token metadata — symbol and name display as text, not {}
|
|
131
|
+
dot query assethub-paseo.Assets.Metadata 50000413
|
|
132
|
+
# { "deposit": "6693666000", "name": "Paseo Token", "symbol": "PAS", ... }
|
|
133
|
+
```
|
|
134
|
+
|
|
105
135
|
### Look up constants
|
|
106
136
|
|
|
107
137
|
```bash
|
|
@@ -153,6 +183,27 @@ dot tx 0x0503008eaf04151687736326c9fea17e25fc5287613693c912909cb226aa4794f26a48
|
|
|
153
183
|
dot tx Utility.batchAll '[{"type":"Balances","value":{"type":"transfer_keep_alive","value":{"dest":"5FHneW46xGXgs5mUiveU4sbTyGBzmstUspZC92UhjJM694ty","value":1000000000000}}},{"type":"Balances","value":{"type":"transfer_keep_alive","value":{"dest":"5FLSigC9HGRKVhB9FiEo4Y3koPsNmBmLJbpXg2mp1hXcS59Y","value":2000000000000}}}]' --from alice
|
|
154
184
|
```
|
|
155
185
|
|
|
186
|
+
#### Enum shorthand
|
|
187
|
+
|
|
188
|
+
Enum arguments accept a concise `Variant(value)` syntax instead of verbose JSON:
|
|
189
|
+
|
|
190
|
+
```bash
|
|
191
|
+
# Instead of: '{"type":"system","value":{"type":"Authorized"}}'
|
|
192
|
+
dot tx Utility.dispatch_as 'system(Authorized)' $(dot tx System.remark 0xcafe --encode) --from alice
|
|
193
|
+
|
|
194
|
+
# Nested enums work too
|
|
195
|
+
dot tx Utility.dispatch_as 'system(Signed(5FHneW46...))' <call> --from alice
|
|
196
|
+
|
|
197
|
+
# Void variants — empty parens or just the name
|
|
198
|
+
dot tx ... 'Root()' ...
|
|
199
|
+
dot tx ... 'Root' ...
|
|
200
|
+
|
|
201
|
+
# JSON inside parens for struct values
|
|
202
|
+
dot tx ... 'AccountId32({"id":"0xd435..."})' ...
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
Variant matching is case-insensitive (`system` resolves to `system`, `authorized` to `Authorized`). All existing formats (JSON objects, hex, SS58 addresses) continue to work unchanged.
|
|
206
|
+
|
|
156
207
|
#### Encode call data
|
|
157
208
|
|
|
158
209
|
Encode a call to hex without signing or submitting. Useful for preparing calls to pass to `Sudo.sudo`, multisig proposals, or governance. Works offline from cached metadata and does not require `--from`.
|
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 = "0.
|
|
8
|
+
var version = "0.10.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";
|
|
@@ -120,6 +120,11 @@ function findAccount(file, name) {
|
|
|
120
120
|
return file.accounts.find((a) => a.name.toLowerCase() === name.toLowerCase());
|
|
121
121
|
}
|
|
122
122
|
|
|
123
|
+
// src/config/accounts-types.ts
|
|
124
|
+
function isEnvSecret(secret) {
|
|
125
|
+
return typeof secret === "object" && secret !== null && "env" in secret;
|
|
126
|
+
}
|
|
127
|
+
|
|
123
128
|
// src/core/accounts.ts
|
|
124
129
|
import { sr25519CreateDerive } from "@polkadot-labs/hdkd";
|
|
125
130
|
import {
|
|
@@ -195,6 +200,27 @@ function toSs58(publicKey, prefix = 42) {
|
|
|
195
200
|
}
|
|
196
201
|
return ss58Address(publicKey, prefix);
|
|
197
202
|
}
|
|
203
|
+
function resolveSecret(secret) {
|
|
204
|
+
if (isEnvSecret(secret)) {
|
|
205
|
+
const value = process.env[secret.env];
|
|
206
|
+
if (!value) {
|
|
207
|
+
throw new Error(`Environment variable "${secret.env}" is not set. Set it before signing.`);
|
|
208
|
+
}
|
|
209
|
+
return value;
|
|
210
|
+
}
|
|
211
|
+
return secret;
|
|
212
|
+
}
|
|
213
|
+
function tryDerivePublicKey(envVarName) {
|
|
214
|
+
const value = process.env[envVarName];
|
|
215
|
+
if (!value)
|
|
216
|
+
return null;
|
|
217
|
+
try {
|
|
218
|
+
const { publicKey } = importAccount(value);
|
|
219
|
+
return publicKeyToHex(publicKey);
|
|
220
|
+
} catch {
|
|
221
|
+
return null;
|
|
222
|
+
}
|
|
223
|
+
}
|
|
198
224
|
async function resolveAccountSigner(name) {
|
|
199
225
|
if (isDevAccount(name)) {
|
|
200
226
|
const keypair2 = getDevKeypair(name);
|
|
@@ -206,12 +232,14 @@ async function resolveAccountSigner(name) {
|
|
|
206
232
|
const available = [...DEV_NAMES, ...accountsFile.accounts.map((a) => a.name)];
|
|
207
233
|
throw new Error(`Unknown account "${name}". Available accounts: ${available.join(", ")}`);
|
|
208
234
|
}
|
|
209
|
-
const
|
|
210
|
-
const
|
|
235
|
+
const secret = resolveSecret(account.secret);
|
|
236
|
+
const isHexSeed = /^0x[0-9a-fA-F]{64}$/.test(secret);
|
|
237
|
+
const keypair = isHexSeed ? deriveFromHexSeed(secret, account.derivationPath) : deriveFromMnemonic(secret, account.derivationPath);
|
|
211
238
|
return getPolkadotSigner(keypair.publicKey, "Sr25519", keypair.sign);
|
|
212
239
|
}
|
|
213
240
|
|
|
214
241
|
// src/core/output.ts
|
|
242
|
+
import { Binary } from "polkadot-api";
|
|
215
243
|
var isTTY = process.stdout.isTTY ?? false;
|
|
216
244
|
var RESET = isTTY ? "\x1B[0m" : "";
|
|
217
245
|
var CYAN = isTTY ? "\x1B[36m" : "";
|
|
@@ -224,6 +252,10 @@ var BOLD = isTTY ? "\x1B[1m" : "";
|
|
|
224
252
|
function replacer(_key, value) {
|
|
225
253
|
if (typeof value === "bigint")
|
|
226
254
|
return value.toString();
|
|
255
|
+
if (value instanceof Binary) {
|
|
256
|
+
const text = value.asText();
|
|
257
|
+
return text.includes("�") ? value.asHex() : text;
|
|
258
|
+
}
|
|
227
259
|
if (value instanceof Uint8Array)
|
|
228
260
|
return `0x${Buffer.from(value).toString("hex")}`;
|
|
229
261
|
return value;
|
|
@@ -304,20 +336,23 @@ var ACCOUNT_HELP = `
|
|
|
304
336
|
${BOLD}Usage:${RESET}
|
|
305
337
|
$ dot account create <name> Create a new account
|
|
306
338
|
$ dot account import <name> --secret <s> Import from BIP39 mnemonic
|
|
339
|
+
$ dot account add <name> --env <VAR> Add account backed by env variable
|
|
307
340
|
$ dot account list List all accounts
|
|
308
341
|
$ dot account remove <name> Remove a stored account
|
|
309
342
|
|
|
310
343
|
${BOLD}Examples:${RESET}
|
|
311
344
|
$ dot account create my-validator
|
|
312
345
|
$ dot account import treasury --secret "word1 word2 ... word12"
|
|
346
|
+
$ dot account add ci-signer --env MY_SECRET
|
|
313
347
|
$ dot account list
|
|
314
348
|
$ dot account remove my-validator
|
|
315
349
|
|
|
316
350
|
${YELLOW}Note: Secrets are stored unencrypted in ~/.polkadot/accounts.json.
|
|
351
|
+
Use --env to keep secrets off disk entirely.
|
|
317
352
|
Hex seed import (0x...) is not supported via CLI.${RESET}
|
|
318
353
|
`.trimStart();
|
|
319
354
|
function registerAccountCommands(cli) {
|
|
320
|
-
cli.command("account [action] [name]", "Manage local accounts (create, import, list, remove)").alias("accounts").option("--secret <value>", "Secret key (mnemonic or hex seed) for import").action(async (action, name, opts) => {
|
|
355
|
+
cli.command("account [action] [name]", "Manage local accounts (create, import, add, list, remove)").alias("accounts").option("--secret <value>", "Secret key (mnemonic or hex seed) for import").option("--env <varName>", "Environment variable name holding the secret").action(async (action, name, opts) => {
|
|
321
356
|
if (!action) {
|
|
322
357
|
return accountList();
|
|
323
358
|
}
|
|
@@ -326,6 +361,8 @@ function registerAccountCommands(cli) {
|
|
|
326
361
|
return accountCreate(name);
|
|
327
362
|
case "import":
|
|
328
363
|
return accountImport(name, opts);
|
|
364
|
+
case "add":
|
|
365
|
+
return accountAdd(name, opts);
|
|
329
366
|
case "list":
|
|
330
367
|
return accountList();
|
|
331
368
|
case "remove":
|
|
@@ -405,6 +442,44 @@ async function accountImport(name, opts) {
|
|
|
405
442
|
console.log(` ${BOLD}Address:${RESET} ${address}`);
|
|
406
443
|
console.log();
|
|
407
444
|
}
|
|
445
|
+
async function accountAdd(name, opts) {
|
|
446
|
+
if (!name) {
|
|
447
|
+
console.error(`Account name is required.
|
|
448
|
+
`);
|
|
449
|
+
console.error("Usage: dot account add <name> --env <VAR>");
|
|
450
|
+
process.exit(1);
|
|
451
|
+
}
|
|
452
|
+
if (!opts.env) {
|
|
453
|
+
console.error(`--env is required.
|
|
454
|
+
`);
|
|
455
|
+
console.error("Usage: dot account add <name> --env <VAR>");
|
|
456
|
+
process.exit(1);
|
|
457
|
+
}
|
|
458
|
+
if (isDevAccount(name)) {
|
|
459
|
+
throw new Error(`"${name}" is a built-in dev account and cannot be used as a custom account name.`);
|
|
460
|
+
}
|
|
461
|
+
const accountsFile = await loadAccounts();
|
|
462
|
+
if (findAccount(accountsFile, name)) {
|
|
463
|
+
throw new Error(`Account "${name}" already exists.`);
|
|
464
|
+
}
|
|
465
|
+
const publicKey = tryDerivePublicKey(opts.env) ?? "";
|
|
466
|
+
accountsFile.accounts.push({
|
|
467
|
+
name,
|
|
468
|
+
secret: { env: opts.env },
|
|
469
|
+
publicKey,
|
|
470
|
+
derivationPath: ""
|
|
471
|
+
});
|
|
472
|
+
await saveAccounts(accountsFile);
|
|
473
|
+
printHeading("Account Added");
|
|
474
|
+
console.log(` ${BOLD}Name:${RESET} ${name}`);
|
|
475
|
+
console.log(` ${BOLD}Env:${RESET} ${opts.env}`);
|
|
476
|
+
if (publicKey) {
|
|
477
|
+
console.log(` ${BOLD}Address:${RESET} ${toSs58(publicKey)}`);
|
|
478
|
+
} else {
|
|
479
|
+
console.log(` ${YELLOW}Address will resolve when $${opts.env} is set.${RESET}`);
|
|
480
|
+
}
|
|
481
|
+
console.log();
|
|
482
|
+
}
|
|
408
483
|
async function accountList() {
|
|
409
484
|
printHeading("Dev Accounts");
|
|
410
485
|
for (const name of DEV_NAMES) {
|
|
@@ -416,8 +491,19 @@ async function accountList() {
|
|
|
416
491
|
if (accountsFile.accounts.length > 0) {
|
|
417
492
|
printHeading("Stored Accounts");
|
|
418
493
|
for (const account of accountsFile.accounts) {
|
|
419
|
-
|
|
420
|
-
|
|
494
|
+
let displayName = account.name;
|
|
495
|
+
let address;
|
|
496
|
+
if (isEnvSecret(account.secret)) {
|
|
497
|
+
displayName += ` (env: ${account.secret.env})`;
|
|
498
|
+
let pubKey = account.publicKey;
|
|
499
|
+
if (!pubKey) {
|
|
500
|
+
pubKey = tryDerivePublicKey(account.secret.env) ?? "";
|
|
501
|
+
}
|
|
502
|
+
address = pubKey ? toSs58(pubKey) : "n/a";
|
|
503
|
+
} else {
|
|
504
|
+
address = toSs58(account.publicKey);
|
|
505
|
+
}
|
|
506
|
+
printItem(displayName, address);
|
|
421
507
|
}
|
|
422
508
|
} else {
|
|
423
509
|
printHeading("Stored Accounts");
|
|
@@ -1201,7 +1287,7 @@ function parseValue(arg) {
|
|
|
1201
1287
|
|
|
1202
1288
|
// src/commands/tx.ts
|
|
1203
1289
|
import { getViewBuilder } from "@polkadot-api/view-builder";
|
|
1204
|
-
import { Binary } from "polkadot-api";
|
|
1290
|
+
import { Binary as Binary2 } from "polkadot-api";
|
|
1205
1291
|
|
|
1206
1292
|
// src/core/explorers.ts
|
|
1207
1293
|
var pjsAppsLink = (rpc, hash) => `https://polkadot.js.org/apps/?rpc=${encodeURIComponent(rpc)}#/explorer/query/${hash}`;
|
|
@@ -1273,8 +1359,8 @@ function normalizeValue(lookup, entry, value) {
|
|
|
1273
1359
|
}
|
|
1274
1360
|
if (innerResolved.type === "primitive" && innerResolved.value === "u8" && typeof value === "string") {
|
|
1275
1361
|
if (/^0x[0-9a-fA-F]*$/.test(value))
|
|
1276
|
-
return
|
|
1277
|
-
return
|
|
1362
|
+
return Binary2.fromHex(value);
|
|
1363
|
+
return Binary2.fromText(value);
|
|
1278
1364
|
}
|
|
1279
1365
|
if (Array.isArray(value)) {
|
|
1280
1366
|
const innerEntry = resolved.value;
|
|
@@ -1329,7 +1415,20 @@ function normalizeValue(lookup, entry, value) {
|
|
|
1329
1415
|
return value;
|
|
1330
1416
|
}
|
|
1331
1417
|
}
|
|
1418
|
+
function parseEnumShorthand(arg) {
|
|
1419
|
+
if (arg.startsWith("{") || arg.startsWith("[") || arg.startsWith("0x"))
|
|
1420
|
+
return null;
|
|
1421
|
+
const firstParen = arg.indexOf("(");
|
|
1422
|
+
if (firstParen === -1 || !arg.endsWith(")"))
|
|
1423
|
+
return null;
|
|
1424
|
+
const variant = arg.slice(0, firstParen);
|
|
1425
|
+
if (!/^[a-zA-Z_]\w*$/.test(variant))
|
|
1426
|
+
return null;
|
|
1427
|
+
return { variant, inner: arg.slice(firstParen + 1, -1) };
|
|
1428
|
+
}
|
|
1332
1429
|
function parseTypedArg(meta, entry, arg) {
|
|
1430
|
+
if (entry.type === "lookupEntry")
|
|
1431
|
+
return parseTypedArg(meta, entry.value, arg);
|
|
1333
1432
|
switch (entry.type) {
|
|
1334
1433
|
case "primitive":
|
|
1335
1434
|
return parsePrimitive(entry.value, arg);
|
|
@@ -1347,7 +1446,7 @@ function parseTypedArg(meta, entry, arg) {
|
|
|
1347
1446
|
case "enum": {
|
|
1348
1447
|
if (/^0x[0-9a-fA-F]+$/.test(arg) && meta.lookup.call != null && entry.id === meta.lookup.call) {
|
|
1349
1448
|
const callCodec = meta.builder.buildDefinition(meta.lookup.call);
|
|
1350
|
-
return callCodec.dec(
|
|
1449
|
+
return callCodec.dec(Binary2.fromHex(arg).asBytes());
|
|
1351
1450
|
}
|
|
1352
1451
|
if (arg.startsWith("{")) {
|
|
1353
1452
|
try {
|
|
@@ -1355,6 +1454,19 @@ function parseTypedArg(meta, entry, arg) {
|
|
|
1355
1454
|
} catch {}
|
|
1356
1455
|
}
|
|
1357
1456
|
const variants = Object.keys(entry.value);
|
|
1457
|
+
const shorthand = parseEnumShorthand(arg);
|
|
1458
|
+
if (shorthand) {
|
|
1459
|
+
const matched2 = variants.find((v) => v.toLowerCase() === shorthand.variant.toLowerCase());
|
|
1460
|
+
if (matched2) {
|
|
1461
|
+
const variantDef = entry.value[matched2];
|
|
1462
|
+
const resolvedDef = variantDef.type === "lookupEntry" ? variantDef.value : variantDef;
|
|
1463
|
+
if (resolvedDef.type === "void" || shorthand.inner === "") {
|
|
1464
|
+
return { type: matched2 };
|
|
1465
|
+
}
|
|
1466
|
+
const innerValue = parseTypedArg(meta, variantDef, shorthand.inner);
|
|
1467
|
+
return normalizeValue(meta.lookup, entry, { type: matched2, value: innerValue });
|
|
1468
|
+
}
|
|
1469
|
+
}
|
|
1358
1470
|
if (variants.includes("Id")) {
|
|
1359
1471
|
const idVariant = entry.value.Id;
|
|
1360
1472
|
const innerType = idVariant.type === "lookupEntry" ? idVariant.value : idVariant;
|
|
@@ -1376,8 +1488,8 @@ function parseTypedArg(meta, entry, arg) {
|
|
|
1376
1488
|
const inner = entry.value;
|
|
1377
1489
|
if (inner.type === "primitive" && inner.value === "u8") {
|
|
1378
1490
|
if (/^0x[0-9a-fA-F]*$/.test(arg))
|
|
1379
|
-
return
|
|
1380
|
-
return
|
|
1491
|
+
return Binary2.fromHex(arg);
|
|
1492
|
+
return Binary2.fromText(arg);
|
|
1381
1493
|
}
|
|
1382
1494
|
if (arg.startsWith("[")) {
|
|
1383
1495
|
try {
|
|
@@ -1385,7 +1497,7 @@ function parseTypedArg(meta, entry, arg) {
|
|
|
1385
1497
|
} catch {}
|
|
1386
1498
|
}
|
|
1387
1499
|
if (/^0x[0-9a-fA-F]*$/.test(arg))
|
|
1388
|
-
return
|
|
1500
|
+
return Binary2.fromHex(arg);
|
|
1389
1501
|
return parseValue(arg);
|
|
1390
1502
|
}
|
|
1391
1503
|
case "struct":
|
|
@@ -1551,7 +1663,7 @@ function parseStorageKeys(meta, palletName, storageItem, args) {
|
|
|
1551
1663
|
|
|
1552
1664
|
// src/commands/tx.ts
|
|
1553
1665
|
import { getViewBuilder as getViewBuilder2 } from "@polkadot-api/view-builder";
|
|
1554
|
-
import { Binary as
|
|
1666
|
+
import { Binary as Binary3 } from "polkadot-api";
|
|
1555
1667
|
function registerTxCommand(cli) {
|
|
1556
1668
|
cli.command("tx [target] [...args]", "Submit an extrinsic (e.g. Balances.transferKeepAlive <dest> <amount>)").option("--from <name>", "Account to sign with (required)").option("--dry-run", "Estimate fees without submitting").option("--encode", "Encode call to hex without signing or submitting").option("--ext <json>", `Custom signed extension values as JSON, e.g. '{"ExtName":{"value":...}}'`).action(async (target, args, opts) => {
|
|
1557
1669
|
if (!target) {
|
|
@@ -1616,7 +1728,7 @@ function registerTxCommand(cli) {
|
|
|
1616
1728
|
throw new Error(`Extra arguments are not allowed when submitting a raw call hex.
|
|
1617
1729
|
` + "Usage: dot tx 0x<call_hex> --from <account>");
|
|
1618
1730
|
}
|
|
1619
|
-
const callBinary =
|
|
1731
|
+
const callBinary = Binary3.fromHex(target);
|
|
1620
1732
|
tx = await unsafeApi.txFromCallData(callBinary);
|
|
1621
1733
|
callHex = target;
|
|
1622
1734
|
} else {
|
|
@@ -1637,7 +1749,7 @@ function registerTxCommand(cli) {
|
|
|
1637
1749
|
const { codec, location } = meta.builder.buildCall(palletInfo.name, callInfo.name);
|
|
1638
1750
|
const encodedArgs = codec.enc(callData);
|
|
1639
1751
|
const fullCall = new Uint8Array([location[0], location[1], ...encodedArgs]);
|
|
1640
|
-
console.log(
|
|
1752
|
+
console.log(Binary3.fromBytes(fullCall).asHex());
|
|
1641
1753
|
return;
|
|
1642
1754
|
}
|
|
1643
1755
|
tx = unsafeApi.tx[palletInfo.name][callInfo.name](callData);
|
|
@@ -1820,6 +1932,10 @@ function formatEventValue(v) {
|
|
|
1820
1932
|
return v.toString();
|
|
1821
1933
|
if (v === null || v === undefined)
|
|
1822
1934
|
return "null";
|
|
1935
|
+
if (v instanceof Binary3) {
|
|
1936
|
+
const text = v.asText();
|
|
1937
|
+
return text.includes("�") ? v.asHex() : text;
|
|
1938
|
+
}
|
|
1823
1939
|
return JSON.stringify(v, (_k, val) => typeof val === "bigint" ? val.toString() : val);
|
|
1824
1940
|
}
|
|
1825
1941
|
function parseCallArgs(meta, palletName, callName, args) {
|
|
@@ -1927,8 +2043,8 @@ function normalizeValue2(lookup, entry, value) {
|
|
|
1927
2043
|
}
|
|
1928
2044
|
if (innerResolved.type === "primitive" && innerResolved.value === "u8" && typeof value === "string") {
|
|
1929
2045
|
if (/^0x[0-9a-fA-F]*$/.test(value))
|
|
1930
|
-
return
|
|
1931
|
-
return
|
|
2046
|
+
return Binary3.fromHex(value);
|
|
2047
|
+
return Binary3.fromText(value);
|
|
1932
2048
|
}
|
|
1933
2049
|
if (Array.isArray(value)) {
|
|
1934
2050
|
const innerEntry = resolved.value;
|
|
@@ -1983,7 +2099,20 @@ function normalizeValue2(lookup, entry, value) {
|
|
|
1983
2099
|
return value;
|
|
1984
2100
|
}
|
|
1985
2101
|
}
|
|
2102
|
+
function parseEnumShorthand2(arg) {
|
|
2103
|
+
if (arg.startsWith("{") || arg.startsWith("[") || arg.startsWith("0x"))
|
|
2104
|
+
return null;
|
|
2105
|
+
const firstParen = arg.indexOf("(");
|
|
2106
|
+
if (firstParen === -1 || !arg.endsWith(")"))
|
|
2107
|
+
return null;
|
|
2108
|
+
const variant = arg.slice(0, firstParen);
|
|
2109
|
+
if (!/^[a-zA-Z_]\w*$/.test(variant))
|
|
2110
|
+
return null;
|
|
2111
|
+
return { variant, inner: arg.slice(firstParen + 1, -1) };
|
|
2112
|
+
}
|
|
1986
2113
|
function parseTypedArg2(meta, entry, arg) {
|
|
2114
|
+
if (entry.type === "lookupEntry")
|
|
2115
|
+
return parseTypedArg2(meta, entry.value, arg);
|
|
1987
2116
|
switch (entry.type) {
|
|
1988
2117
|
case "primitive":
|
|
1989
2118
|
return parsePrimitive2(entry.value, arg);
|
|
@@ -2001,7 +2130,7 @@ function parseTypedArg2(meta, entry, arg) {
|
|
|
2001
2130
|
case "enum": {
|
|
2002
2131
|
if (/^0x[0-9a-fA-F]+$/.test(arg) && meta.lookup.call != null && entry.id === meta.lookup.call) {
|
|
2003
2132
|
const callCodec = meta.builder.buildDefinition(meta.lookup.call);
|
|
2004
|
-
return callCodec.dec(
|
|
2133
|
+
return callCodec.dec(Binary3.fromHex(arg).asBytes());
|
|
2005
2134
|
}
|
|
2006
2135
|
if (arg.startsWith("{")) {
|
|
2007
2136
|
try {
|
|
@@ -2009,6 +2138,19 @@ function parseTypedArg2(meta, entry, arg) {
|
|
|
2009
2138
|
} catch {}
|
|
2010
2139
|
}
|
|
2011
2140
|
const variants = Object.keys(entry.value);
|
|
2141
|
+
const shorthand = parseEnumShorthand2(arg);
|
|
2142
|
+
if (shorthand) {
|
|
2143
|
+
const matched2 = variants.find((v) => v.toLowerCase() === shorthand.variant.toLowerCase());
|
|
2144
|
+
if (matched2) {
|
|
2145
|
+
const variantDef = entry.value[matched2];
|
|
2146
|
+
const resolvedDef = variantDef.type === "lookupEntry" ? variantDef.value : variantDef;
|
|
2147
|
+
if (resolvedDef.type === "void" || shorthand.inner === "") {
|
|
2148
|
+
return { type: matched2 };
|
|
2149
|
+
}
|
|
2150
|
+
const innerValue = parseTypedArg2(meta, variantDef, shorthand.inner);
|
|
2151
|
+
return normalizeValue2(meta.lookup, entry, { type: matched2, value: innerValue });
|
|
2152
|
+
}
|
|
2153
|
+
}
|
|
2012
2154
|
if (variants.includes("Id")) {
|
|
2013
2155
|
const idVariant = entry.value.Id;
|
|
2014
2156
|
const innerType = idVariant.type === "lookupEntry" ? idVariant.value : idVariant;
|
|
@@ -2030,8 +2172,8 @@ function parseTypedArg2(meta, entry, arg) {
|
|
|
2030
2172
|
const inner = entry.value;
|
|
2031
2173
|
if (inner.type === "primitive" && inner.value === "u8") {
|
|
2032
2174
|
if (/^0x[0-9a-fA-F]*$/.test(arg))
|
|
2033
|
-
return
|
|
2034
|
-
return
|
|
2175
|
+
return Binary3.fromHex(arg);
|
|
2176
|
+
return Binary3.fromText(arg);
|
|
2035
2177
|
}
|
|
2036
2178
|
if (arg.startsWith("[")) {
|
|
2037
2179
|
try {
|
|
@@ -2039,7 +2181,7 @@ function parseTypedArg2(meta, entry, arg) {
|
|
|
2039
2181
|
} catch {}
|
|
2040
2182
|
}
|
|
2041
2183
|
if (/^0x[0-9a-fA-F]*$/.test(arg))
|
|
2042
|
-
return
|
|
2184
|
+
return Binary3.fromHex(arg);
|
|
2043
2185
|
return parseValue(arg);
|
|
2044
2186
|
}
|
|
2045
2187
|
case "struct":
|