@everyprotocol/every-cli 0.1.2 → 0.1.4
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/.every.toml +8 -10
- package/abis/ElementRegistry.json +1 -1
- package/abis/IObjectMinter.json +1 -1
- package/abis/IObjectMinterAdmin.json +1 -1
- package/abis/IOmniRegistry.json +1 -1
- package/abis/ISet.json +1 -1
- package/abis/ISetRegistry.json +1 -1
- package/abis/ISetRegistryAdmin.json +1 -1
- package/abis/KindRegistry.json +1 -1
- package/abis/ObjectMinter.json +1 -1
- package/abis/OmniRegistry.json +1 -1
- package/abis/SetRegistry.json +1 -1
- package/dist/abi.js +6 -0
- package/dist/cmdgen.js +51 -139
- package/dist/cmds/balance.js +43 -0
- package/dist/cmds/config.js +46 -0
- package/dist/cmds/kind.js +14 -0
- package/dist/cmds/matter.js +82 -0
- package/dist/cmds/minter.js +31 -0
- package/dist/cmds/object.js +175 -0
- package/dist/cmds/relation.js +16 -0
- package/dist/cmds/set.js +31 -0
- package/dist/cmds/unique.js +14 -0
- package/dist/cmds/universe.js +21 -0
- package/dist/cmds/value.js +14 -0
- package/dist/cmds/wallet.js +90 -0
- package/dist/commander-patch.js +64 -0
- package/dist/config.js +62 -51
- package/dist/ethereum.js +33 -0
- package/dist/from-opts.js +161 -0
- package/dist/index.js +2 -1
- package/dist/keystore.js +120 -0
- package/dist/logger.js +39 -0
- package/dist/parsers.js +59 -0
- package/dist/program.js +28 -39
- package/dist/substrate.js +63 -0
- package/dist/utils.js +150 -147
- package/package.json +4 -1
- package/dist/cmds.js +0 -132
- package/dist/matter.js +0 -152
- package/dist/mint.js +0 -64
- package/dist/relate.js +0 -104
- package/dist/wallet.js +0 -108
package/dist/logger.js
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import * as fs from "fs";
|
|
2
|
+
import { stringify as j11 } from "json11";
|
|
3
|
+
import path from "path";
|
|
4
|
+
export class Logger {
|
|
5
|
+
quiet;
|
|
6
|
+
json;
|
|
7
|
+
constructor(opts = {}) {
|
|
8
|
+
this.quiet = opts.quiet ?? !!opts.json;
|
|
9
|
+
this.json = opts.json ?? false;
|
|
10
|
+
}
|
|
11
|
+
log(...args) {
|
|
12
|
+
if (!this.quiet)
|
|
13
|
+
console.error(...args);
|
|
14
|
+
}
|
|
15
|
+
warn(...args) {
|
|
16
|
+
if (!this.quiet)
|
|
17
|
+
console.error("[warn]", ...args);
|
|
18
|
+
}
|
|
19
|
+
error(...args) {
|
|
20
|
+
console.error("[error]", ...args);
|
|
21
|
+
}
|
|
22
|
+
result(data) {
|
|
23
|
+
const opts = {
|
|
24
|
+
quote: `"`,
|
|
25
|
+
quoteNames: true,
|
|
26
|
+
withBigInt: false,
|
|
27
|
+
};
|
|
28
|
+
if (this.json) {
|
|
29
|
+
if (typeof this.json === "string") {
|
|
30
|
+
const dir = path.dirname(this.json);
|
|
31
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
32
|
+
fs.writeFileSync(this.json, j11(data, opts));
|
|
33
|
+
}
|
|
34
|
+
else {
|
|
35
|
+
console.log(j11(data, opts)); // stdout
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
package/dist/parsers.js
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { u8aFixLength } from "@polkadot/util";
|
|
2
|
+
import { decodeAddress } from "@polkadot/util-crypto";
|
|
3
|
+
import { InvalidArgumentError } from "commander";
|
|
4
|
+
export function parseBigInt(arg) {
|
|
5
|
+
try {
|
|
6
|
+
return BigInt(arg);
|
|
7
|
+
}
|
|
8
|
+
catch (e /* eslint-disable-line */) {
|
|
9
|
+
throw new InvalidArgumentError("invalid bigint");
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
export function parseAccountId(address) {
|
|
13
|
+
try {
|
|
14
|
+
return u8aFixLength(decodeAddress(address), 256);
|
|
15
|
+
}
|
|
16
|
+
catch (e /* eslint-disable-line */) {
|
|
17
|
+
throw new InvalidArgumentError("invalid account ID");
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
export function parseNode4(arg) {
|
|
21
|
+
const parts = arg.split(".");
|
|
22
|
+
let [data, grant, set, id] = [0n, 0n, 0n, 0n];
|
|
23
|
+
if (parts.length == 2) {
|
|
24
|
+
set = BigInt(parts[0]);
|
|
25
|
+
id = BigInt(parts[1]);
|
|
26
|
+
}
|
|
27
|
+
else if (parts.length == 3) {
|
|
28
|
+
grant = BigInt(parts[0]);
|
|
29
|
+
set = BigInt(parts[1]);
|
|
30
|
+
id = BigInt(parts[2]);
|
|
31
|
+
}
|
|
32
|
+
else if (parts.length == 4) {
|
|
33
|
+
data = BigInt(parts[0]);
|
|
34
|
+
grant = BigInt(parts[1]);
|
|
35
|
+
set = BigInt(parts[2]);
|
|
36
|
+
id = BigInt(parts[3]);
|
|
37
|
+
}
|
|
38
|
+
else {
|
|
39
|
+
throw new InvalidArgumentError("invalid Node4");
|
|
40
|
+
}
|
|
41
|
+
return (data << 192n) | (grant << 128n) | (set << 64n) | id;
|
|
42
|
+
}
|
|
43
|
+
export function parseNode3(arg) {
|
|
44
|
+
const parts = arg.split(".");
|
|
45
|
+
let [grant, set, id] = [0n, 0n, 0n];
|
|
46
|
+
if (parts.length == 2) {
|
|
47
|
+
set = BigInt(parts[0]);
|
|
48
|
+
id = BigInt(parts[1]);
|
|
49
|
+
}
|
|
50
|
+
else if (parts.length == 3) {
|
|
51
|
+
grant = BigInt(parts[0]);
|
|
52
|
+
set = BigInt(parts[1]);
|
|
53
|
+
id = BigInt(parts[2]);
|
|
54
|
+
}
|
|
55
|
+
else {
|
|
56
|
+
throw new InvalidArgumentError("invalid Node3");
|
|
57
|
+
}
|
|
58
|
+
return (grant << 128n) | (set << 64n) | id;
|
|
59
|
+
}
|
package/dist/program.js
CHANGED
|
@@ -1,41 +1,30 @@
|
|
|
1
1
|
import { Command } from "commander";
|
|
2
|
-
import { generateCommands } from "./cmdgen.js";
|
|
3
|
-
import { RenamingCommand } from "./cmds.js";
|
|
4
2
|
import { version } from "./utils.js";
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
program.addCommand(uniqueCmd);
|
|
34
|
-
program.addCommand(valueCmd);
|
|
35
|
-
program.addCommand(objectCmd);
|
|
36
|
-
program.addCommand(mintPolicyCmd);
|
|
37
|
-
program.addCommand(genWalletCommands());
|
|
38
|
-
program.addCommand(genMatterCommand());
|
|
39
|
-
return program;
|
|
40
|
-
}
|
|
41
|
-
export const program = buildProgram();
|
|
3
|
+
import { walletCmd } from "./cmds/wallet.js";
|
|
4
|
+
import { matterCmd } from "./cmds/matter.js";
|
|
5
|
+
import { balanceCmd } from "./cmds/balance.js";
|
|
6
|
+
import { configCmd } from "./cmds/config.js";
|
|
7
|
+
import { kindCmd } from "./cmds/kind.js";
|
|
8
|
+
import { valueCmd } from "./cmds/value.js";
|
|
9
|
+
import { uniqueCmd } from "./cmds/unique.js";
|
|
10
|
+
import { relationCmd } from "./cmds/relation.js";
|
|
11
|
+
import { setCmd } from "./cmds/set.js";
|
|
12
|
+
import { objectCmd } from "./cmds/object.js";
|
|
13
|
+
import { minterCmd } from "./cmds/minter.js";
|
|
14
|
+
import { universeCmd } from "./cmds/universe.js";
|
|
15
|
+
export const program = new Command("every")
|
|
16
|
+
.description("CLI for interacting with Every Protocol")
|
|
17
|
+
.version(version())
|
|
18
|
+
.showHelpAfterError(true)
|
|
19
|
+
.addCommand(universeCmd)
|
|
20
|
+
.addCommand(matterCmd)
|
|
21
|
+
.addCommand(setCmd)
|
|
22
|
+
.addCommand(kindCmd)
|
|
23
|
+
.addCommand(relationCmd)
|
|
24
|
+
.addCommand(valueCmd)
|
|
25
|
+
.addCommand(uniqueCmd)
|
|
26
|
+
.addCommand(objectCmd)
|
|
27
|
+
.addCommand(minterCmd)
|
|
28
|
+
.addCommand(balanceCmd)
|
|
29
|
+
.addCommand(walletCmd)
|
|
30
|
+
.addCommand(configCmd);
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import "@polkadot/api-augment/substrate";
|
|
2
|
+
import { decodeAddress } from "@polkadot/util-crypto";
|
|
3
|
+
import { u8aFixLength } from "@polkadot/util";
|
|
4
|
+
import * as JSON11 from "json11";
|
|
5
|
+
import columify from "columnify";
|
|
6
|
+
import { createDeferred } from "./utils.js";
|
|
7
|
+
import "./commander-patch.js";
|
|
8
|
+
export async function submitTransaction(api, tx, pair) {
|
|
9
|
+
const pTxn = createDeferred();
|
|
10
|
+
const pReceipt = createDeferred();
|
|
11
|
+
const accountId = u8aFixLength(decodeAddress(pair.address), 256);
|
|
12
|
+
const nonce = await api.rpc.system.accountNextIndex(accountId);
|
|
13
|
+
const unsub = await tx.signAndSend(pair, { nonce }, (result) => {
|
|
14
|
+
const { status, txHash, events, dispatchError } = result;
|
|
15
|
+
if (dispatchError) {
|
|
16
|
+
if (dispatchError.isModule) {
|
|
17
|
+
const meta = api.registry.findMetaError(dispatchError.asModule);
|
|
18
|
+
const msg = `${meta.section}.${meta.name}${meta.docs.length ? `: ${meta.docs.join(" ")}` : ""}`;
|
|
19
|
+
unsub();
|
|
20
|
+
pReceipt.reject(new Error(`DispatchError: ${msg}`));
|
|
21
|
+
}
|
|
22
|
+
else {
|
|
23
|
+
unsub();
|
|
24
|
+
pReceipt.reject(new Error(dispatchError.toString()));
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
if (status.isReady) {
|
|
28
|
+
pTxn.resolve({ txHash: txHash.toHex(), receipt: pReceipt.promise });
|
|
29
|
+
}
|
|
30
|
+
if (status.isFinalized) {
|
|
31
|
+
unsub();
|
|
32
|
+
pReceipt.resolve({
|
|
33
|
+
txHash: txHash.toHex(),
|
|
34
|
+
blockHash: status.asFinalized.toHex(),
|
|
35
|
+
events: events,
|
|
36
|
+
result,
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
});
|
|
40
|
+
return await pTxn.promise;
|
|
41
|
+
}
|
|
42
|
+
export async function submitSubTxUI(api, tx, pair, console) {
|
|
43
|
+
console.log(`Transaction submitting...`);
|
|
44
|
+
const txn = await submitTransaction(api, tx, pair);
|
|
45
|
+
console.log(`Transaction submitted: ${txn.txHash}`);
|
|
46
|
+
console.log("Waiting for confirmation...");
|
|
47
|
+
const r = await txn.receipt;
|
|
48
|
+
const header = await api.rpc.chain.getHeader(r.blockHash);
|
|
49
|
+
console.log(`Confirmed in: block ${header.number}, hash ${header.hash}`);
|
|
50
|
+
const events = r.events.map((e, i) => [i, e.event.method, JSON11.stringify(e.event.data.toJSON())]);
|
|
51
|
+
const result = r.events.map((e) => {
|
|
52
|
+
const event = {
|
|
53
|
+
event: e.event.method,
|
|
54
|
+
data: e.event.data.toJSON(),
|
|
55
|
+
};
|
|
56
|
+
return event;
|
|
57
|
+
});
|
|
58
|
+
if (events.length > 0) {
|
|
59
|
+
console.log(`Events`);
|
|
60
|
+
console.log(columify(events, { showHeaders: false }));
|
|
61
|
+
}
|
|
62
|
+
console.result(result);
|
|
63
|
+
}
|
package/dist/utils.js
CHANGED
|
@@ -1,125 +1,25 @@
|
|
|
1
|
-
import { bytesToHex, createPublicClient, createWalletClient, encodeAbiParameters, http, } from "viem";
|
|
2
|
-
import { formatAbiParameter } from "abitype";
|
|
3
1
|
import fs from "fs";
|
|
4
2
|
import path from "path";
|
|
5
|
-
import { Wallet } from "ethers";
|
|
6
|
-
import { privateKeyToAccount } from "viem/accounts";
|
|
7
|
-
import promptSync from "prompt-sync";
|
|
8
|
-
import os from "os";
|
|
9
|
-
import JSON5 from "json5";
|
|
10
3
|
import { fileURLToPath } from "url";
|
|
11
4
|
import { isHex, hexToU8a } from "@polkadot/util";
|
|
12
5
|
import { base64Decode } from "@polkadot/util-crypto/base64";
|
|
13
6
|
import { decodePair } from "@polkadot/keyring/pair/decode";
|
|
14
|
-
import
|
|
7
|
+
import { getAddress, isAddress, pad, sha256 } from "viem";
|
|
8
|
+
import { FromOpts } from "./from-opts.js";
|
|
15
9
|
export const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
16
10
|
export function version() {
|
|
17
11
|
const pkgPath = path.resolve(__dirname, "../package.json");
|
|
18
12
|
return JSON.parse(fs.readFileSync(pkgPath, "utf-8")).version;
|
|
19
13
|
}
|
|
20
|
-
export function lstrip(prefix) {
|
|
21
|
-
return function (func) {
|
|
22
|
-
return func.name.startsWith(prefix) ? func.name.substring(prefix.length).toLowerCase() : func.name;
|
|
23
|
-
};
|
|
24
|
-
}
|
|
25
|
-
export function rstrip(postfix) {
|
|
26
|
-
return function (func) {
|
|
27
|
-
return func.name.endsWith(postfix) ? func.name.slice(0, -postfix.length) : func.name;
|
|
28
|
-
};
|
|
29
|
-
}
|
|
30
|
-
export function startsWith(prefix) {
|
|
31
|
-
return function (func) {
|
|
32
|
-
return func.name.startsWith(prefix);
|
|
33
|
-
};
|
|
34
|
-
}
|
|
35
|
-
export function excludes(names) {
|
|
36
|
-
return function (func) {
|
|
37
|
-
return !names.includes(func.name);
|
|
38
|
-
};
|
|
39
|
-
}
|
|
40
|
-
export function includes(names) {
|
|
41
|
-
return function (f) {
|
|
42
|
-
return names.includes(f.name);
|
|
43
|
-
};
|
|
44
|
-
}
|
|
45
|
-
export function stringify(o) {
|
|
46
|
-
const replacer = (_key, value) => (typeof value === "bigint" ? value.toString() : value);
|
|
47
|
-
return JSON5.stringify(o, replacer);
|
|
48
|
-
}
|
|
49
|
-
export async function getClientsEth(uniConf, opts) {
|
|
50
|
-
const transport = http(uniConf.rpc);
|
|
51
|
-
const publicClient = createPublicClient({ transport });
|
|
52
|
-
const privateKey = await readPrivateKeyEth(opts);
|
|
53
|
-
const account = privateKeyToAccount(privateKey);
|
|
54
|
-
const walletClient = createWalletClient({ account, transport });
|
|
55
|
-
return { publicClient, walletClient };
|
|
56
|
-
}
|
|
57
|
-
export async function readPrivateKeyEth(opts) {
|
|
58
|
-
if (opts.privateKey) {
|
|
59
|
-
return opts.privateKey.startsWith("0x") ? opts.privateKey : `0x${opts.privateKey}`;
|
|
60
|
-
}
|
|
61
|
-
else if (opts.account) {
|
|
62
|
-
const keystorePath = resolveKeystoreFile(opts.account, opts);
|
|
63
|
-
const keystore = loadKeystore(keystorePath);
|
|
64
|
-
if (keystore.crypto || keystore.Crypto) {
|
|
65
|
-
// for Ethereum keystores
|
|
66
|
-
const password = getPassword(opts);
|
|
67
|
-
const wallet = await Wallet.fromEncryptedJson(JSON.stringify(keystore), password);
|
|
68
|
-
return wallet.privateKey;
|
|
69
|
-
}
|
|
70
|
-
else if (keystore.encoding || keystore.meta) {
|
|
71
|
-
// for Substrate keystores
|
|
72
|
-
if (keystore.meta?.isEthereum || keystore.meta?.type === "ethereum") {
|
|
73
|
-
const password = getPassword(opts);
|
|
74
|
-
const pair = decodeSubstratePair(keystore, password);
|
|
75
|
-
return bytesToHex(pair.secretKey);
|
|
76
|
-
}
|
|
77
|
-
else {
|
|
78
|
-
throw new Error("Not an Ethereum account");
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
else {
|
|
82
|
-
// Not supported for now
|
|
83
|
-
throw new Error("Unknown keystore format");
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
else {
|
|
87
|
-
throw new Error(`Neither account nor private key specified`);
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
14
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
91
|
-
export function
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
const pt = abiParam?.type;
|
|
95
|
-
const arg = pt === "address" || pt.startsWith("bytes") || pt === "string" ? rawArg : JSON5.parse(rawArg);
|
|
96
|
-
try {
|
|
97
|
-
encodeAbiParameters([abiParam], [arg]);
|
|
98
|
-
}
|
|
99
|
-
catch (e) {
|
|
100
|
-
if (e instanceof Error) {
|
|
101
|
-
throw new Error(`invalid param ${formatAbiParameter(abiParam)}\n${e.message}`);
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
return arg;
|
|
105
|
-
});
|
|
106
|
-
}
|
|
107
|
-
export function resolveKeystoreDir(options) {
|
|
108
|
-
if (options.foundry) {
|
|
109
|
-
return path.join(os.homedir(), ".foundry", "keystores");
|
|
110
|
-
}
|
|
111
|
-
if (options.dir) {
|
|
112
|
-
return options.dir;
|
|
15
|
+
export function loadJson(file) {
|
|
16
|
+
if (!fs.existsSync(file)) {
|
|
17
|
+
throw new Error(`Keystore file not found: ${file}`);
|
|
113
18
|
}
|
|
114
|
-
return
|
|
115
|
-
}
|
|
116
|
-
export function resolveKeystoreFile(name, options) {
|
|
117
|
-
const dir = resolveKeystoreDir(options);
|
|
118
|
-
return path.join(dir, name);
|
|
19
|
+
return JSON.parse(fs.readFileSync(file, "utf8"));
|
|
119
20
|
}
|
|
120
|
-
// eslint-disable-next-line
|
|
121
|
-
export function
|
|
122
|
-
const dir = resolveKeystoreDir(options);
|
|
21
|
+
// eslint-disable-next-line
|
|
22
|
+
export function saveJson(json, dir, name) {
|
|
123
23
|
if (!fs.existsSync(dir)) {
|
|
124
24
|
fs.mkdirSync(dir, { recursive: true });
|
|
125
25
|
}
|
|
@@ -128,54 +28,157 @@ export function saveKeystore(json, name, options) {
|
|
|
128
28
|
throw new Error(`File exists: ${file}`);
|
|
129
29
|
}
|
|
130
30
|
fs.writeFileSync(file, JSON.stringify(json));
|
|
131
|
-
console.log(`File saved: ${file}`);
|
|
132
31
|
}
|
|
133
32
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
134
|
-
export function
|
|
135
|
-
|
|
136
|
-
|
|
33
|
+
export function decodePairFromJson(keystore, password) {
|
|
34
|
+
const encodedRaw = keystore.encoded;
|
|
35
|
+
let encodingType = keystore.encoding.type;
|
|
36
|
+
encodingType = !Array.isArray(encodingType) ? [encodingType] : encodingType;
|
|
37
|
+
const encoded = isHex(encodedRaw) ? hexToU8a(encodedRaw) : base64Decode(encodedRaw);
|
|
38
|
+
const decoded = decodePair(password, encoded, encodingType);
|
|
39
|
+
return decoded;
|
|
40
|
+
}
|
|
41
|
+
export function guessContentType(filePath) {
|
|
42
|
+
const ext = path.extname(filePath).toLowerCase();
|
|
43
|
+
switch (ext) {
|
|
44
|
+
case ".txt":
|
|
45
|
+
return "text/plain";
|
|
46
|
+
case ".json":
|
|
47
|
+
return "application/json";
|
|
48
|
+
case ".wasm":
|
|
49
|
+
return "application/wasm";
|
|
50
|
+
case ".jpg":
|
|
51
|
+
case ".jpeg":
|
|
52
|
+
return "image/jpeg";
|
|
53
|
+
case ".png":
|
|
54
|
+
return "image/png";
|
|
55
|
+
default:
|
|
56
|
+
return "application/octet-stream";
|
|
137
57
|
}
|
|
138
|
-
return JSON.parse(fs.readFileSync(file, "utf8"));
|
|
139
58
|
}
|
|
140
|
-
export function
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
59
|
+
export function createDeferred() {
|
|
60
|
+
let resolve;
|
|
61
|
+
let reject;
|
|
62
|
+
const promise = new Promise((res, rej) => {
|
|
63
|
+
resolve = res;
|
|
64
|
+
reject = rej;
|
|
65
|
+
});
|
|
66
|
+
return { promise, resolve, reject };
|
|
67
|
+
}
|
|
68
|
+
const isArrayType = (t) => /\[[^\]]*\]$/.test(t);
|
|
69
|
+
const isTupleType = (t) => t.startsWith("tuple");
|
|
70
|
+
const elemType = (t) => t.replace(/\[[^\]]*\]$/, "");
|
|
71
|
+
// const fmtInputs = (ins: ReadonlyArray<Pick<AbiParameter, "name" | "type">>) =>
|
|
72
|
+
// ins.map((i) => (i.name ? `${i.type} ${i.name}` : i.type)).join(", ");
|
|
73
|
+
function hasComponents(p) {
|
|
74
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
75
|
+
return p.components !== "undefined";
|
|
76
|
+
}
|
|
77
|
+
function coerceScalar(val, type) {
|
|
78
|
+
const base = elemType(type);
|
|
79
|
+
if (base === "address") {
|
|
80
|
+
if (!isAddress(val))
|
|
81
|
+
throw new Error(`Invalid address: ${val}`);
|
|
82
|
+
return getAddress(val);
|
|
83
|
+
}
|
|
84
|
+
if (base === "bool") {
|
|
85
|
+
if (!/^(true|false)$/i.test(val))
|
|
86
|
+
throw new Error(`Invalid bool: ${val}`);
|
|
87
|
+
return /^true$/i.test(val);
|
|
88
|
+
}
|
|
89
|
+
if (base === "string")
|
|
90
|
+
return val;
|
|
91
|
+
if (base.startsWith("bytes")) {
|
|
92
|
+
if (!/^0x[0-9a-fA-F]*$/.test(val))
|
|
93
|
+
throw new Error(`Invalid ${base} (expect 0x...)`);
|
|
94
|
+
return val;
|
|
95
|
+
}
|
|
96
|
+
if (base.startsWith("uint") || base.startsWith("int")) {
|
|
97
|
+
try {
|
|
98
|
+
return val.startsWith("0x") ? BigInt(val) : BigInt(val);
|
|
99
|
+
}
|
|
100
|
+
catch {
|
|
101
|
+
throw new Error(`Invalid ${base}: ${val}`);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
return val;
|
|
105
|
+
}
|
|
106
|
+
export function coerceValue(val, param) {
|
|
107
|
+
const { type } = param;
|
|
108
|
+
// arrays: expect JSON array; recurse on element type (preserve components if tuple[])
|
|
109
|
+
if (isArrayType(type)) {
|
|
110
|
+
const arr = JSON.parse(val);
|
|
111
|
+
if (!Array.isArray(arr))
|
|
112
|
+
throw new Error(`Expected array for ${type}`);
|
|
113
|
+
// build element param (carry tuple components if present)
|
|
114
|
+
const inner = hasComponents(param)
|
|
115
|
+
? { ...param, type: elemType(type), components: param.components }
|
|
116
|
+
: { ...param, type: elemType(type) };
|
|
117
|
+
return arr.map((v) => coerceValue(typeof v === "string" ? v : JSON.stringify(v), inner));
|
|
118
|
+
}
|
|
119
|
+
// tuples: need components
|
|
120
|
+
if (isTupleType(type)) {
|
|
121
|
+
if (!hasComponents(param) || param.components.length === 0) {
|
|
122
|
+
throw new Error(`Tuple components missing for ${type}`);
|
|
123
|
+
}
|
|
124
|
+
const tup = JSON.parse(val);
|
|
125
|
+
if (Array.isArray(tup)) {
|
|
126
|
+
if (tup.length !== param.components.length) {
|
|
127
|
+
throw new Error(`Tuple length mismatch: expected ${param.components.length}, got ${tup.length}`);
|
|
128
|
+
}
|
|
129
|
+
return param.components.map((c, i) => coerceValue(typeof tup[i] === "string" ? tup[i] : JSON.stringify(tup[i]), c));
|
|
130
|
+
}
|
|
131
|
+
// object by names
|
|
132
|
+
return param.components.map((c) => {
|
|
133
|
+
const v = tup[c.name];
|
|
134
|
+
if (v === undefined)
|
|
135
|
+
throw new Error(`Tuple field missing: ${c.name}`);
|
|
136
|
+
return coerceValue(typeof v === "string" ? v : JSON.stringify(v), c);
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
// scalar
|
|
140
|
+
return coerceScalar(val, type);
|
|
146
141
|
}
|
|
147
|
-
export function
|
|
148
|
-
|
|
149
|
-
return
|
|
142
|
+
export async function substrateAction(cmd, api, fn) {
|
|
143
|
+
try {
|
|
144
|
+
return await fn(api);
|
|
150
145
|
}
|
|
151
|
-
|
|
152
|
-
|
|
146
|
+
catch (e /* eslint-disable-line */) {
|
|
147
|
+
cmd.error(e.message);
|
|
153
148
|
}
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
const confirmation = prompt("Confirm: ", { echo: "" });
|
|
157
|
-
if (password !== confirmation) {
|
|
158
|
-
throw new Error(`Error: Passwords do not match`);
|
|
149
|
+
finally {
|
|
150
|
+
api.disconnect().catch(() => { });
|
|
159
151
|
}
|
|
160
|
-
return password;
|
|
161
152
|
}
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
153
|
+
export function wrapSubAction(fn) {
|
|
154
|
+
// eslint-disable-next-line
|
|
155
|
+
return async function (...args) {
|
|
156
|
+
const api = await FromOpts.getSubstrateApi(this.opts());
|
|
157
|
+
try {
|
|
158
|
+
// keep Commander’s `this` binding and pass api first
|
|
159
|
+
return await fn.call(this, api, ...args);
|
|
160
|
+
}
|
|
161
|
+
finally {
|
|
162
|
+
await api.disconnect().catch(() => { });
|
|
163
|
+
}
|
|
164
|
+
};
|
|
170
165
|
}
|
|
171
|
-
export function
|
|
172
|
-
const
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
if (
|
|
177
|
-
|
|
178
|
-
|
|
166
|
+
export function loadBinary(file) {
|
|
167
|
+
const buf = fs.readFileSync(file);
|
|
168
|
+
return buf;
|
|
169
|
+
}
|
|
170
|
+
export function computeMatterHash(form, mime, blob) {
|
|
171
|
+
if (!Number.isInteger(form) || form < 0 || form > 255) {
|
|
172
|
+
throw new Error("form must be uint8 (0..255)");
|
|
173
|
+
}
|
|
174
|
+
const mimeUTF8 = new TextEncoder().encode(mime);
|
|
175
|
+
if (mimeUTF8.length <= 0 || mimeUTF8.length > 31) {
|
|
176
|
+
throw new Error("form must be uint8 (0..255)");
|
|
179
177
|
}
|
|
180
|
-
|
|
178
|
+
const msg = new Uint8Array(1 + 31 + blob.length);
|
|
179
|
+
msg[0] = form & 0xff;
|
|
180
|
+
msg.set(pad(mimeUTF8, { size: 32, dir: "right" }), 1);
|
|
181
|
+
msg.set(blob, 32);
|
|
182
|
+
// SHA256(form:1 || mime:31 || blob:var)
|
|
183
|
+
return sha256(msg);
|
|
181
184
|
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@everyprotocol/every-cli",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.1.
|
|
4
|
+
"version": "0.1.4",
|
|
5
5
|
"files": [
|
|
6
6
|
"dist/",
|
|
7
7
|
"abis/",
|
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
"devDependencies": {
|
|
16
16
|
"@eslint/js": "^9.26.0",
|
|
17
17
|
"@types/bun": "latest",
|
|
18
|
+
"@types/columnify": "^1.5.4",
|
|
18
19
|
"@types/lodash-es": "^4.17.12",
|
|
19
20
|
"@types/prompt-sync": "^4.2.3",
|
|
20
21
|
"@typescript-eslint/eslint-plugin": "^8.32.1",
|
|
@@ -32,8 +33,10 @@
|
|
|
32
33
|
"@polkadot/keyring": "^13.5.2",
|
|
33
34
|
"@polkadot/util": "^13.5.2",
|
|
34
35
|
"@polkadot/util-crypto": "^13.5.2",
|
|
36
|
+
"columnify": "^1.6.0",
|
|
35
37
|
"commander": "^13.1.0",
|
|
36
38
|
"ethers": "^6.14.0",
|
|
39
|
+
"json11": "^2.0.2",
|
|
37
40
|
"json5": "^2.2.3",
|
|
38
41
|
"lodash-es": "^4.17.21",
|
|
39
42
|
"prompt-sync": "^4.2.0",
|