@everyprotocol/every-cli 0.1.3 → 0.1.5

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/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 { walletCmd } from "./wallet.js";
6
- import { genMatterCommand } from "./matter.js";
7
- function buildProgram() {
8
- const subCmds = generateCommands();
9
- const kindCmd = new RenamingCommand().name("kind").description("manage kinds").addCommands(subCmds.kind);
10
- const setCmd = new RenamingCommand().name("set").description("manage sets").addCommands(subCmds.set);
11
- const relationCmd = new RenamingCommand()
12
- .name("relation")
13
- .description("manage relations")
14
- .addCommands(subCmds.relation);
15
- const uniqueCmd = new RenamingCommand().name("unique").description("manage uniques").addCommands(subCmds.unique);
16
- const valueCmd = new RenamingCommand().name("value").description("manage values").addCommands(subCmds.value);
17
- const objectCmd = new RenamingCommand()
18
- .name("object")
19
- .description("create and interact with objects")
20
- .addCommands(subCmds.object);
21
- const mintPolicyCmd = new RenamingCommand()
22
- .name("minter")
23
- .description("manage mint policies")
24
- .addCommands(subCmds.mintpolicy);
25
- const program = new Command()
26
- .name("every")
27
- .description("CLI for interacting with Every Protocol")
28
- .version(version())
29
- .showHelpAfterError(true);
30
- program.addCommand(genMatterCommand());
31
- program.addCommand(setCmd);
32
- program.addCommand(kindCmd);
33
- program.addCommand(relationCmd);
34
- program.addCommand(valueCmd);
35
- program.addCommand(uniqueCmd);
36
- program.addCommand(objectCmd);
37
- program.addCommand(mintPolicyCmd);
38
- program.addCommand(walletCmd);
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);
package/dist/substrate.js CHANGED
@@ -1,19 +1,11 @@
1
1
  import "@polkadot/api-augment/substrate";
2
2
  import { decodeAddress } from "@polkadot/util-crypto";
3
3
  import { u8aFixLength } from "@polkadot/util";
4
- import "./options.js";
5
- function createDeferred() {
6
- let resolve;
7
- let reject;
8
- const promise = new Promise((res, rej) => {
9
- resolve = res;
10
- reject = rej;
11
- });
12
- return { promise, resolve, reject };
13
- }
4
+ import * as JSON11 from "json11";
5
+ import columify from "columnify";
6
+ import { createDeferred } from "./utils.js";
7
+ import "./commander-patch.js";
14
8
  export async function submitTransaction(api, tx, pair) {
15
- // const pTxn = Promise.withResolvers<Transaction>();
16
- // const pReceipt = Promise.withResolvers<Receipt>();
17
9
  const pTxn = createDeferred();
18
10
  const pReceipt = createDeferred();
19
11
  const accountId = u8aFixLength(decodeAddress(pair.address), 256);
@@ -47,11 +39,25 @@ export async function submitTransaction(api, tx, pair) {
47
39
  });
48
40
  return await pTxn.promise;
49
41
  }
50
- export function findEvent(events, name) {
51
- for (const record of events) {
52
- if (record.event && record.event.method === name) {
53
- return record.event;
54
- }
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 }));
55
61
  }
56
- return undefined;
62
+ console.result(result);
57
63
  }
package/dist/utils.js CHANGED
@@ -1,127 +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 { loadMergedConfig } from "./config.js";
15
- import Keyring from "@polkadot/keyring";
16
- import { UnifiedKeystore } from "./keystore.js";
7
+ import { getAddress, isAddress } from "viem";
8
+ import { FromOpts } from "./from-opts.js";
17
9
  export const __dirname = path.dirname(fileURLToPath(import.meta.url));
18
10
  export function version() {
19
11
  const pkgPath = path.resolve(__dirname, "../package.json");
20
12
  return JSON.parse(fs.readFileSync(pkgPath, "utf-8")).version;
21
13
  }
22
- export function lstrip(prefix) {
23
- return function (func) {
24
- return func.name.startsWith(prefix) ? func.name.substring(prefix.length).toLowerCase() : func.name;
25
- };
26
- }
27
- export function rstrip(postfix) {
28
- return function (func) {
29
- return func.name.endsWith(postfix) ? func.name.slice(0, -postfix.length) : func.name;
30
- };
31
- }
32
- export function startsWith(prefix) {
33
- return function (func) {
34
- return func.name.startsWith(prefix);
35
- };
36
- }
37
- export function excludes(names) {
38
- return function (func) {
39
- return !names.includes(func.name);
40
- };
41
- }
42
- export function includes(names) {
43
- return function (f) {
44
- return names.includes(f.name);
45
- };
46
- }
47
- export function stringify(o) {
48
- const replacer = (_key, value) => (typeof value === "bigint" ? value.toString() : value);
49
- return JSON5.stringify(o, replacer);
50
- }
51
- export async function getClientsEth(uniConf, opts) {
52
- const transport = http(uniConf.rpc);
53
- const publicClient = createPublicClient({ transport });
54
- const privateKey = await readPrivateKeyEth(opts);
55
- const account = privateKeyToAccount(privateKey);
56
- const walletClient = createWalletClient({ account, transport });
57
- return { publicClient, walletClient };
58
- }
59
- export async function readPrivateKeyEth(opts) {
60
- if (opts.privateKey) {
61
- return opts.privateKey.startsWith("0x") ? opts.privateKey : `0x${opts.privateKey}`;
62
- }
63
- else if (opts.account) {
64
- const keystorePath = resolveKeystoreFile(opts.account, opts);
65
- const keystore = loadKeystore(keystorePath);
66
- if (keystore.crypto || keystore.Crypto) {
67
- // for Ethereum keystores
68
- const password = getPassword(opts);
69
- const wallet = await Wallet.fromEncryptedJson(JSON.stringify(keystore), password);
70
- return wallet.privateKey;
71
- }
72
- else if (keystore.encoding || keystore.meta) {
73
- // for Substrate keystores
74
- if (keystore.meta?.isEthereum || keystore.meta?.type === "ethereum") {
75
- const password = getPassword(opts);
76
- const pair = decodeSubstratePair(keystore, password);
77
- return bytesToHex(pair.secretKey);
78
- }
79
- else {
80
- throw new Error("Not an Ethereum account");
81
- }
82
- }
83
- else {
84
- // Not supported for now
85
- throw new Error("Unknown keystore format");
86
- }
87
- }
88
- else {
89
- throw new Error(`Neither account nor private key specified`);
90
- }
91
- }
92
14
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
93
- export function checkArguments(raw, func) {
94
- return raw.map((rawArg, index) => {
95
- const abiParam = func.inputs[index];
96
- const pt = abiParam?.type;
97
- const arg = pt === "address" || pt.startsWith("bytes") || pt === "string" ? rawArg : JSON5.parse(rawArg);
98
- try {
99
- encodeAbiParameters([abiParam], [arg]);
100
- }
101
- catch (e) {
102
- if (e instanceof Error) {
103
- throw new Error(`invalid param ${formatAbiParameter(abiParam)}\n${e.message}`);
104
- }
105
- }
106
- return arg;
107
- });
108
- }
109
- export function resolveKeystoreDir(options) {
110
- if (options.foundry) {
111
- return path.join(os.homedir(), ".foundry", "keystores");
112
- }
113
- if (options.dir) {
114
- return options.dir;
15
+ export function loadJson(file) {
16
+ if (!fs.existsSync(file)) {
17
+ throw new Error(`Keystore file not found: ${file}`);
115
18
  }
116
- return path.join(os.homedir(), ".every", "keystores");
117
- }
118
- export function resolveKeystoreFile(name, options) {
119
- const dir = resolveKeystoreDir(options);
120
- return path.join(dir, name);
19
+ return JSON.parse(fs.readFileSync(file, "utf8"));
121
20
  }
122
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
123
- export function saveKeystore(json, name, options) {
124
- const dir = resolveKeystoreDir(options);
21
+ // eslint-disable-next-line
22
+ export function saveJson(json, dir, name) {
125
23
  if (!fs.existsSync(dir)) {
126
24
  fs.mkdirSync(dir, { recursive: true });
127
25
  }
@@ -130,39 +28,9 @@ export function saveKeystore(json, name, options) {
130
28
  throw new Error(`File exists: ${file}`);
131
29
  }
132
30
  fs.writeFileSync(file, JSON.stringify(json));
133
- console.log(`File saved: ${file}`);
134
- }
135
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
136
- export function loadKeystore(file) {
137
- if (!fs.existsSync(file)) {
138
- throw new Error(`Keystore file not found: ${file}`);
139
- }
140
- return JSON.parse(fs.readFileSync(file, "utf8"));
141
- }
142
- export function getPassword(opts) {
143
- return opts.password
144
- ? opts.password
145
- : opts.passwordFile
146
- ? fs.readFileSync(opts.passwordFile, "utf8").trim()
147
- : promptSync({ sigint: true })("Password: ", { echo: "" });
148
- }
149
- export function getPasswordConfirm(opts) {
150
- if (opts.password) {
151
- return opts.password;
152
- }
153
- if (opts.passwordFile) {
154
- return fs.readFileSync(opts.passwordFile, "utf8").trim();
155
- }
156
- const prompt = promptSync({ sigint: true });
157
- const password = prompt("Password: ", { echo: "" });
158
- const confirmation = prompt("Confirm: ", { echo: "" });
159
- if (password !== confirmation) {
160
- throw new Error(`Error: Passwords do not match`);
161
- }
162
- return password;
163
31
  }
164
32
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
165
- export function decodeSubstratePair(keystore, password) {
33
+ export function decodePairFromJson(keystore, password) {
166
34
  const encodedRaw = keystore.encoded;
167
35
  let encodingType = keystore.encoding.type;
168
36
  encodingType = !Array.isArray(encodingType) ? [encodingType] : encodingType;
@@ -170,53 +38,132 @@ export function decodeSubstratePair(keystore, password) {
170
38
  const decoded = decodePair(password, encoded, encodingType);
171
39
  return decoded;
172
40
  }
173
- export function getSubstrateAccountPair(flags) {
174
- const keyFile = resolveKeystoreFile(flags.account, flags);
175
- const keyData = loadKeystore(keyFile);
176
- const keyring = new Keyring();
177
- const pair = keyring.createFromJson(keyData);
178
- if (pair.isLocked) {
179
- const password = getPassword(flags);
180
- pair.unlock(password);
181
- }
182
- return pair;
183
- }
184
- export async function keystoreFromOptions(options) {
185
- if (!options.account) {
186
- throw new Error("Account must be specified with --account");
187
- }
188
- return keystoreFromAccount(options.account, options);
189
- }
190
- export async function keystoreFromAccount(account, options) {
191
- const file = resolveKeystoreFile(account, options);
192
- const keyData = loadKeystore(file);
193
- const password = getPassword(options);
194
- const keystore = await UnifiedKeystore.fromJSON(keyData, password);
195
- return keystore;
196
- }
197
- export function getObserverConfig(options) {
198
- const conf = loadMergedConfig();
199
- let observerName;
200
- const DEFAULT_OBSERVER = "localnet";
201
- if (options.observer) {
202
- observerName = options.observer;
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";
57
+ }
58
+ }
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
+ }
203
103
  }
204
- else if (options.universe) {
205
- const universe = conf.universes[options.universe];
206
- if (!universe) {
207
- throw new Error(`Universe '${options.universe}' not found in config. Available: ${Object.keys(conf.universes).join(", ")}`);
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));
208
130
  }
209
- observerName = universe.observer;
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
+ });
210
138
  }
211
- else {
212
- observerName = DEFAULT_OBSERVER;
139
+ // scalar
140
+ return coerceScalar(val, type);
141
+ }
142
+ export async function substrateAction(cmd, api, fn) {
143
+ try {
144
+ return await fn(api);
213
145
  }
214
- if (!observerName) {
215
- throw new Error(`No observer resolved from options or config.`);
146
+ catch (e /* eslint-disable-line */) {
147
+ cmd.error(e.message);
216
148
  }
217
- const observer = conf.observers[observerName];
218
- if (!observer) {
219
- throw new Error(`Observer '${observerName}' not found in config. Available: ${Object.keys(conf.observers).join(", ")}`);
149
+ finally {
150
+ api.disconnect().catch(() => { });
220
151
  }
221
- return observer;
152
+ }
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
+ };
165
+ }
166
+ export function loadBinary(file) {
167
+ const buf = fs.readFileSync(file);
168
+ return buf;
222
169
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@everyprotocol/every-cli",
3
3
  "type": "module",
4
- "version": "0.1.3",
4
+ "version": "0.1.5",
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,11 @@
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",
38
+ "csv-parser": "^3.2.0",
36
39
  "ethers": "^6.14.0",
40
+ "json11": "^2.0.2",
37
41
  "json5": "^2.2.3",
38
42
  "lodash-es": "^4.17.21",
39
43
  "prompt-sync": "^4.2.0",
package/dist/cmds.js DELETED
@@ -1,132 +0,0 @@
1
- import { Argument, Command, Option } from "commander";
2
- import { createPublicClient, http, parseEventLogs, stringify } from "viem";
3
- import { getUniverseConfig } from "./config.js";
4
- import { checkArguments, getClientsEth } from "./utils.js";
5
- export function defaultReadFunctionOptions() {
6
- const options = [];
7
- options.push(new Option("-u, --universe <universe>", "universe name").default("local"));
8
- options.push(new Option("--dry-run", "Simulate the command without sending a transaction"));
9
- return options;
10
- }
11
- export function defaultWriteFunctionOptions() {
12
- const options = [];
13
- options.push(new Option("-u, --universe <universe>", "universe name").default("local"));
14
- options.push(new Option("-k, --private-key <key>", "private key to sign the transaction"));
15
- options.push(new Option("-a, --account <account>", "name of the keystore to sign the transaction"));
16
- options.push(new Option("-p, --password [password]", "password to decrypt the keystore"));
17
- options.push(new Option("--password-file <file>", "file containing the password to decrypt the keystore"));
18
- options.push(new Option("-f, --foundry", "use keystore from Foundry directory (~/.foundry/keystores)"));
19
- options.push(new Option("--dry-run", "Simulate the command without sending a transaction"));
20
- return options;
21
- }
22
- const defaultConfig = {
23
- cmdAbi: (txnAbi) => txnAbi,
24
- cmdName: (cmdAbi) => cmdAbi.name,
25
- cmdDescription: (cmdAbi) => cmdAbi._metadata?.notice || cmdAbi.name,
26
- cmdOptions: (cmdAbi) => {
27
- const read = cmdAbi.stateMutability == "view" || cmdAbi.stateMutability == "pure";
28
- return read ? defaultReadFunctionOptions() : defaultWriteFunctionOptions();
29
- },
30
- cmdArguments: (cmdAbi) => cmdAbi.inputs.map((input) => {
31
- const argDesc = cmdAbi._metadata?.params?.[input.name] || `${input.type} parameter`;
32
- return new Argument(`<${input.name}>`, argDesc);
33
- }),
34
- cmdAction: async function (ctx) {
35
- const isRead = ctx.cmdAbi.stateMutability == "view" || ctx.cmdAbi.stateMutability == "pure";
36
- const opts = ctx.cmd.opts();
37
- const args0 = ctx.cmd.args;
38
- console.log({ args0 });
39
- const { address, tag, args } = await ctx.txnPrepare(ctx);
40
- const abi = [ctx.txnAbi, ...ctx.nonFuncs];
41
- const functionName = ctx.txnAbi.name;
42
- if (isRead) {
43
- const publicClient = createPublicClient({ transport: http(ctx.conf.rpc) });
44
- const result = await publicClient.readContract({ address, abi, functionName, args });
45
- console.log(`Result:`, result);
46
- }
47
- else {
48
- const { publicClient, walletClient } = await getClientsEth(ctx.conf, opts);
49
- const account = walletClient.account;
50
- console.log({
51
- isRead,
52
- address: `${address} (${tag})`,
53
- account: account?.address,
54
- signature: ctx.txnAbi._metadata.signature,
55
- args,
56
- });
57
- const { request } = await publicClient.simulateContract({ address, abi, functionName, args, account });
58
- const hash = await walletClient.writeContract(request);
59
- console.log(`Transaction sent: ${hash}`);
60
- console.log("Transaction mining...");
61
- const receipt = await publicClient.waitForTransactionReceipt({ hash });
62
- console.log("Transaction mined");
63
- if (receipt.logs && receipt.logs.length > 0) {
64
- const parsedLogs = parseEventLogs({ abi, logs: receipt.logs });
65
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
66
- parsedLogs.forEach((log) => {
67
- console.log(" - Event", log.eventName, stringify(log.args));
68
- });
69
- }
70
- }
71
- console.log({ isRead, address: `${address} (${tag})`, signature: ctx.txnAbi._metadata.signature, args });
72
- return;
73
- },
74
- txnPrepare: function (ctx) {
75
- const args = checkArguments(ctx.cmd.args, ctx.cmdAbi);
76
- return { address: ctx.conf.contracts[ctx.contract], tag: ctx.contract, args };
77
- },
78
- };
79
- export function configureCommand(txnAbi, config) {
80
- const cmdAbi = (config.cmdAbi || defaultConfig.cmdAbi)(txnAbi);
81
- const name = (config.cmdName || defaultConfig.cmdName)(cmdAbi);
82
- const desc = (config.cmdDescription || defaultConfig.cmdDescription)(cmdAbi);
83
- const opts = (config.cmdOptions || defaultConfig.cmdOptions)(cmdAbi);
84
- const args = (config.cmdArguments || defaultConfig.cmdArguments)(cmdAbi);
85
- const action = async function () {
86
- const ctx = {
87
- conf: getUniverseConfig(this.opts()),
88
- contract: config.contract,
89
- cmdAbi,
90
- txnAbi,
91
- nonFuncs: config.nonFuncs,
92
- cmd: this,
93
- txnPrepare: config.txnPrepare || defaultConfig.txnPrepare,
94
- };
95
- await (config.cmdAction || defaultConfig.cmdAction)(ctx);
96
- };
97
- const cmd = new Command();
98
- cmd.name(name);
99
- cmd.description(desc);
100
- opts.forEach((opt) => cmd.addOption(opt));
101
- args.forEach((arg) => cmd.addArgument(arg));
102
- cmd.action(action);
103
- return cmd;
104
- }
105
- export class RenamingCommand extends Command {
106
- nameCounts = new Map();
107
- addCommand(cmd, opts) {
108
- const originalName = cmd.name();
109
- const uniqueName = this.getUniqueName(originalName);
110
- if (originalName !== uniqueName) {
111
- cmd.name(uniqueName);
112
- }
113
- return super.addCommand(cmd, opts);
114
- }
115
- addCommands(cmds) {
116
- cmds.forEach((cmd) => this.addCommand(cmd));
117
- return this;
118
- }
119
- resetCounts(name) {
120
- if (name) {
121
- this.nameCounts.delete(name);
122
- }
123
- else {
124
- this.nameCounts.clear();
125
- }
126
- }
127
- getUniqueName(baseName) {
128
- const count = this.nameCounts.get(baseName) || 0;
129
- this.nameCounts.set(baseName, count + 1);
130
- return count === 0 ? baseName : `${baseName}${count + 1}`;
131
- }
132
- }