From 72eb8f0fc9168fb0e2ed140a669af83c5573cad4 Mon Sep 17 00:00:00 2001 From: Igor Papandinas Date: Mon, 25 Mar 2024 16:51:11 +0400 Subject: [PATCH] Revert "feat: Implement system/local config + support default/dev account (#62)" This reverts commit 4ef3ca2fea2bf91fa3e8fa96d77e9b30e451c6f8. --- src/commands/account/create.ts | 40 ++--------- src/commands/account/default.ts | 82 ---------------------- src/commands/account/list.ts | 31 +-------- src/commands/check/index.ts | 20 +++--- src/commands/contract/compile.ts | 29 +++----- src/commands/contract/deploy.ts | 58 +++++++--------- src/commands/contract/explain.ts | 3 +- src/commands/contract/new.ts | 15 ++-- src/commands/contract/query.ts | 6 +- src/commands/contract/test.ts | 4 +- src/commands/contract/tx.ts | 6 +- src/commands/contract/verify.ts | 21 ++---- src/commands/generate/types.ts | 8 +-- src/commands/init/index.ts | 79 +++++++++++++++++---- src/commands/node/install.ts | 32 +++++---- src/commands/node/start.ts | 5 +- src/lib/command-utils.ts | 107 +++-------------------------- src/lib/config-builder.ts | 70 ------------------- src/lib/consts.ts | 4 -- src/lib/contractCall.ts | 55 ++++++--------- src/lib/swankyCommand.ts | 114 +++++-------------------------- src/types/index.ts | 10 +-- 22 files changed, 210 insertions(+), 589 deletions(-) delete mode 100644 src/commands/account/default.ts delete mode 100644 src/lib/config-builder.ts diff --git a/src/commands/account/create.ts b/src/commands/account/create.ts index 8972f8af..a9000c4a 100644 --- a/src/commands/account/create.ts +++ b/src/commands/account/create.ts @@ -1,37 +1,22 @@ import { Flags } from "@oclif/core"; import chalk from "chalk"; -import { ChainAccount, encrypt, getSwankyConfig, isLocalConfigCheck } from "../../lib/index.js"; +import { ChainAccount, encrypt } from "../../lib/index.js"; import { AccountData } from "../../types/index.js"; import inquirer from "inquirer"; -import { SwankyCommand } from "../../lib/swankyCommand.js"; -import { FileError } from "../../lib/errors.js"; -import { ConfigBuilder } from "../../lib/config-builder.js"; import { SwankyAccountCommand } from "./swankyAccountCommands.js"; export class CreateAccount extends SwankyAccountCommand { static description = "Create a new dev account in config"; static flags = { - global: Flags.boolean({ + generate: Flags.boolean({ char: "g", - description: "Create account globally stored in Swanky system config.", - - }), - new: Flags.boolean({ - char: "n", - description: "Generate a brand new account.", }), dev: Flags.boolean({ char: "d", - description: "Make this account a dev account for local network usage.", }), }; - constructor(argv: string[], baseConfig: any) { - super(argv, baseConfig); - (this.constructor as typeof SwankyCommand).ENSURE_SWANKY_CONFIG = false; - } - async run(): Promise { const { flags } = await this.parse(CreateAccount); @@ -51,8 +36,8 @@ export class CreateAccount extends SwankyAccountCommand { ); } - let tmpMnemonic = ""; - if (flags.new) { + let tmpMnemonic: string; + if (flags.generate) { tmpMnemonic = ChainAccount.generate(); console.log( `${ @@ -91,22 +76,9 @@ export class CreateAccount extends SwankyAccountCommand { accountData.mnemonic = tmpMnemonic; } - const configType = flags.global ? "global" : isLocalConfigCheck() ? "local" : "global"; - const config = configType === "global" ? getSwankyConfig("global") : getSwankyConfig("local"); - - const configBuilder = new ConfigBuilder(config).addAccount(accountData); + this.swankyConfig.accounts.push(accountData); - if (config.defaultAccount === null) { - configBuilder.setDefaultAccount(accountData.alias); - } - - try { - await this.storeConfig(configBuilder.build(), configType); - } catch (cause) { - throw new FileError(`Error storing created account in ${configType} config`, { - cause, - }); - } + await this.storeConfig(); this.log( `${chalk.greenBright("✔")} Account with alias ${chalk.yellowBright( diff --git a/src/commands/account/default.ts b/src/commands/account/default.ts deleted file mode 100644 index 7ffdb422..00000000 --- a/src/commands/account/default.ts +++ /dev/null @@ -1,82 +0,0 @@ -import { Args, Flags } from "@oclif/core"; -import chalk from "chalk"; -import { SwankySystemConfig } from "../../types/index.js"; -import inquirer from "inquirer"; -import { SwankyCommand } from "../../lib/swankyCommand.js"; -import { ConfigError, FileError } from "../../lib/errors.js"; -import { getSwankyConfig, isLocalConfigCheck } from "../../lib/index.js"; -import { ConfigBuilder } from "../../lib/config-builder.js"; - -export class DefaultAccount extends SwankyCommand { - static description = "Set default account to use"; - - static flags = { - global: Flags.boolean({ - char: "g", - description: "Set default account globally in Swanky system config.", - }), - }; - - static args = { - accountAlias: Args.string({ - name: "accountAlias", - required: false, - description: "Alias of account to be used as default", - }), - }; - - constructor(argv: string[], baseConfig: any) { - super(argv, baseConfig); - (this.constructor as typeof SwankyCommand).ENSURE_SWANKY_CONFIG = false; - } - - async run(): Promise { - const { args, flags } = await this.parse(DefaultAccount); - - const configType = flags.global ? "global" : isLocalConfigCheck() ? "local" : "global"; - const config = configType === "global" ? getSwankyConfig("global") : getSwankyConfig("local"); - - const accountAlias = args.accountAlias ?? (await this.promptForAccountAlias(config)); - this.ensureAccountExists(config, accountAlias); - - const newConfig = new ConfigBuilder(config).setDefaultAccount(accountAlias).build(); - - try { - await this.storeConfig(newConfig, configType); - } catch (cause) { - throw new FileError(`Error storing default account in ${configType} config`, { - cause, - }); - } - - this.log( - `${chalk.greenBright("✔")} Account with alias ${chalk.yellowBright( - accountAlias - )} set as default in ${configType} config` - ); - } - - private async promptForAccountAlias(config: SwankySystemConfig): Promise { - const choices = config.accounts.map((account) => ({ - name: `${account.alias} (${account.address})`, - value: account.alias, - })); - - const answer = await inquirer.prompt([ - { - type: "list", - name: "defaultAccount", - message: "Select default account", - choices: choices, - }, - ]); - - return answer.defaultAccount; - } - - private ensureAccountExists(config: SwankySystemConfig, alias: string) { - const isSomeAccount = config.accounts.some((account) => account.alias === alias); - if (!isSomeAccount) - throw new ConfigError(`Provided account alias ${chalk.yellowBright(alias)} not found`); - } -} diff --git a/src/commands/account/list.ts b/src/commands/account/list.ts index 67f05ecd..a7c294bd 100644 --- a/src/commands/account/list.ts +++ b/src/commands/account/list.ts @@ -5,36 +5,11 @@ export class ListAccounts extends SwankyCommand { static description = "List dev accounts stored in config"; static aliases = [`account:ls`]; - constructor(argv: string[], baseConfig: any) { - super(argv, baseConfig); - (this.constructor as typeof SwankyCommand).ENSURE_SWANKY_CONFIG = false; - } - async run(): Promise { - const countOfDevAccounts = this.swankyConfig.accounts.filter((account) => account.isDev).length; - - if(countOfDevAccounts !== 0) { - this.log(`${chalk.greenBright("✔")} Stored dev accounts:`); - - for (const account of this.swankyConfig.accounts) { - if(account.isDev){ - this.log(`\t${chalk.yellowBright("Alias: ")} ${account.alias} \ -${chalk.yellowBright("Address: ")} ${account.address} ${this.swankyConfig.defaultAccount === account.alias ? chalk.greenBright("<- Default") : ""}`); - } - } - } - - const countOfProdAccounts = this.swankyConfig.accounts.length - countOfDevAccounts; - - if(countOfProdAccounts !== 0) { - this.log(`${chalk.greenBright("✔")} Stored prod accounts:`); + this.log(`${chalk.greenBright("✔")} Stored dev accounts:`); - for (const account of this.swankyConfig.accounts) { - if(!account.isDev){ - this.log(`\t${chalk.yellowBright("Alias: ")} ${account.alias} \ -${chalk.yellowBright("Address: ")} ${account.address} ${this.swankyConfig.defaultAccount === account.alias ? chalk.greenBright("<- Default") : ""}`); - } - } + for (const account of this.swankyConfig.accounts) { + this.log(`\t${chalk.yellowBright("Alias: ")} ${account.alias}`); } } } diff --git a/src/commands/check/index.ts b/src/commands/check/index.ts index eaa169fe..1875a8eb 100644 --- a/src/commands/check/index.ts +++ b/src/commands/check/index.ts @@ -1,7 +1,7 @@ import { Listr } from "listr2"; import { commandStdoutOrNull, extractCargoContractVersion } from "../../lib/index.js"; import { SwankyConfig } from "../../types/index.js"; -import { pathExistsSync, writeJson } from "fs-extra/esm"; +import { pathExistsSync, readJSON, writeJson } from "fs-extra/esm"; import { readFileSync } from "fs"; import path from "node:path"; import TOML from "@iarna/toml"; @@ -31,7 +31,7 @@ interface Ctx { contracts: Record>; swankyNode: string | null; }; - swankyConfig: SwankyConfig; + swankyConfig?: SwankyConfig; mismatchedVersions: Record; looseDefinitionDetected: boolean; } @@ -46,16 +46,11 @@ export default class Check extends SwankyCommand { }), }; - constructor(argv: string[], baseConfig: any) { - super(argv, baseConfig); - (this.constructor as typeof SwankyCommand).ENSURE_SWANKY_CONFIG = false; - } - public async run(): Promise { const { flags } = await this.parse(Check); const swankyNodeVersion = this.swankyConfig.node.version; const isSwankyNodeInstalled = !!swankyNodeVersion; - const anyContracts = Object.keys(this.swankyConfig.contracts ?? {}).length > 0; + const anyContracts = Object.keys(this.swankyConfig?.contracts).length > 0; const tasks = new Listr([ { title: "Check OS", @@ -141,9 +136,11 @@ export default class Check extends SwankyCommand { { title: "Read ink dependencies", enabled: anyContracts, - skip: (ctx) => Object.keys(ctx.swankyConfig.contracts).length == 0, task: async (ctx) => { - for (const contract in ctx.swankyConfig.contracts) { + const swankyConfig = await readJSON("swanky.config.json"); + ctx.swankyConfig = swankyConfig; + + for (const contract in swankyConfig.contracts) { const tomlPath = path.resolve(`contracts/${contract}/Cargo.toml`); const doesCargoTomlExist = pathExistsSync(tomlPath); if (!doesCargoTomlExist) { @@ -171,7 +168,7 @@ export default class Check extends SwankyCommand { skip: (ctx) => Object.keys(ctx.versions.contracts).length === 0, enabled: anyContracts && isSwankyNodeInstalled, task: async (ctx) => { - const supportedInk = ctx.swankyConfig.node.supportedInk; + const supportedInk = ctx.swankyConfig!.node.supportedInk; const mismatched: Record = {}; Object.entries(ctx.versions.contracts).forEach(([contract, inkDependencies]) => { Object.entries(inkDependencies).forEach(([depName, version]) => { @@ -259,7 +256,6 @@ export default class Check extends SwankyCommand { contracts: {}, swankyNode: swankyNodeVersion || null, }, - swankyConfig: this.swankyConfig, looseDefinitionDetected: false, mismatchedVersions: {} }); diff --git a/src/commands/contract/compile.ts b/src/commands/contract/compile.ts index 93a00538..56d87283 100644 --- a/src/commands/contract/compile.ts +++ b/src/commands/contract/compile.ts @@ -3,10 +3,9 @@ import path from "node:path"; import { spawn } from "node:child_process"; import { pathExists } from "fs-extra/esm"; import { SwankyCommand } from "../../lib/swankyCommand.js"; -import { ensureCargoContractVersionCompatibility, extractCargoContractVersion, Spinner, storeArtifacts, configName, getSwankyConfig } from "../../lib/index.js"; +import { ensureCargoContractVersionCompatibility, extractCargoContractVersion, Spinner, storeArtifacts } from "../../lib/index.js"; import { ConfigError, InputError, ProcessError } from "../../lib/errors.js"; -import { BuildMode, SwankyConfig } from "../../index.js"; -import { ConfigBuilder } from "../../lib/config-builder.js"; +import { BuildMode } from "../../index.js"; export class CompileContract extends SwankyCommand { static description = "Compile the smart contract(s) in your contracts directory"; @@ -42,8 +41,6 @@ export class CompileContract extends SwankyCommand { async run(): Promise { const { args, flags } = await this.parse(CompileContract); - const localConfig = getSwankyConfig("local") as SwankyConfig; - if (args.contractName === undefined && !flags.all) { throw new InputError("No contracts were selected to compile", { winston: { stack: true } }); } @@ -58,7 +55,7 @@ export class CompileContract extends SwankyCommand { const contractInfo = this.swankyConfig.contracts[contractName]; if (!contractInfo) { throw new ConfigError( - `Cannot find contract info for ${contractName} contract in "${configName()}"` + `Cannot find contract info for ${contractName} contract in swanky.config.json`, ); } const contractPath = path.resolve("contracts", contractInfo.name); @@ -133,18 +130,14 @@ export class CompileContract extends SwankyCommand { return storeArtifacts(artifactsPath, contractInfo.name, contractInfo.moduleName); }, "Moving artifacts"); - await this.spinner.runCommand(async () => { - const buildData = { - timestamp: Date.now(), - artifactsPath, - buildMode, - isVerified: false, - }; - const newLocalConfig = new ConfigBuilder(localConfig) - .addContractBuild(args.contractName, buildData) - .build(); - await this.storeConfig(newLocalConfig, "local"); - }, "Writing config"); + this.swankyConfig.contracts[contractName].build = { + timestamp: Date.now(), + artifactsPath, + buildMode, + isVerified: false, + }; + + await this.storeConfig(); } } } diff --git a/src/commands/contract/deploy.ts b/src/commands/contract/deploy.ts index 44d3cd8d..ac3489b4 100644 --- a/src/commands/contract/deploy.ts +++ b/src/commands/contract/deploy.ts @@ -1,20 +1,22 @@ import { Args, Flags } from "@oclif/core"; +import path from "node:path"; +import { writeJSON } from "fs-extra/esm"; import { cryptoWaitReady } from "@polkadot/util-crypto/crypto"; -import { AbiType, ChainAccount, ChainApi, decrypt, resolveNetworkUrl, ensureAccountIsSet, configName, getSwankyConfig } from "../../lib/index.js"; -import { BuildMode, Encrypted, SwankyConfig } from "../../types/index.js"; +import { AbiType, ChainAccount, ChainApi, decrypt, resolveNetworkUrl } from "../../lib/index.js"; +import { BuildMode, Encrypted } from "../../types/index.js"; import inquirer from "inquirer"; import chalk from "chalk"; import { Contract } from "../../lib/contract.js"; import { SwankyCommand } from "../../lib/swankyCommand.js"; -import { ApiError, ConfigError, FileError, InputError, ProcessError } from "../../lib/errors.js"; -import { ConfigBuilder } from "../../lib/config-builder.js"; +import { ApiError, ConfigError, FileError, ProcessError } from "../../lib/errors.js"; export class DeployContract extends SwankyCommand { static description = "Deploy contract to a running node"; static flags = { account: Flags.string({ - description: "Account alias to deploy contract with", + required: true, + description: "Alias of account to be used", }), gas: Flags.integer({ char: "g", @@ -30,7 +32,6 @@ export class DeployContract extends SwankyCommand { }), network: Flags.string({ char: "n", - default: "local", description: "Network name to connect to", }), }; @@ -46,11 +47,10 @@ export class DeployContract extends SwankyCommand { async run(): Promise { const { args, flags } = await this.parse(DeployContract); - const localConfig = getSwankyConfig("local") as SwankyConfig; - const contractRecord = localConfig.contracts[args.contractName]; + const contractRecord = this.swankyConfig.contracts[args.contractName]; if (!contractRecord) { throw new ConfigError( - `Cannot find a contract named ${args.contractName} in "${configName()}"` + `Cannot find a contract named ${args.contractName} in swanky.config.json` ); } @@ -97,22 +97,7 @@ export class DeployContract extends SwankyCommand { }); } - ensureAccountIsSet(flags.account, this.swankyConfig); - - const accountAlias = flags.account ?? this.swankyConfig.defaultAccount; - - if (accountAlias === null) { - throw new InputError(`An account is required to deploy ${args.contractName}`); - } - - const accountData = this.findAccountByAlias(accountAlias); - - if (accountData.isDev && flags.network !== "local") { - throw new ConfigError( - `Account ${accountAlias} is a DEV account and can only be used with local network` - ); - } - + const accountData = this.findAccountByAlias(flags.account); const mnemonic = accountData.isDev ? (accountData.mnemonic as string) : decrypt( @@ -164,16 +149,19 @@ export class DeployContract extends SwankyCommand { }, "Deploying")) as string; await this.spinner.runCommand(async () => { - const deploymentData = { - timestamp: Date.now(), - address: contractAddress, - networkUrl, - deployerAlias: accountAlias, - }; - const newLocalConfig = new ConfigBuilder(localConfig) - .addContractDeployment(args.contractName, deploymentData) - .build(); - await this.storeConfig(newLocalConfig, "local"); + contractRecord.deployments = [ + ...contractRecord.deployments, + { + timestamp: Date.now(), + address: contractAddress, + networkUrl, + deployerAlias: flags.account, + }, + ]; + + await writeJSON(path.resolve("swanky.config.json"), this.swankyConfig, { + spaces: 2, + }); }, "Writing config"); this.log(`Contract deployed!`); diff --git a/src/commands/contract/explain.ts b/src/commands/contract/explain.ts index 3efba84e..b171338d 100644 --- a/src/commands/contract/explain.ts +++ b/src/commands/contract/explain.ts @@ -2,7 +2,6 @@ import { SwankyCommand } from "../../lib/swankyCommand.js"; import { Args } from "@oclif/core"; import { Contract } from "../../lib/contract.js"; import { ConfigError, FileError } from "../../lib/errors.js"; -import { configName } from "../../lib/index.js"; export class ExplainContract extends SwankyCommand { static description = "Explain contract messages based on the contracts' metadata"; @@ -21,7 +20,7 @@ export class ExplainContract extends SwankyCommand { const contractRecord = this.swankyConfig.contracts[args.contractName]; if (!contractRecord) { throw new ConfigError( - `Cannot find a contract named ${args.contractName} in "${configName()}"` + `Cannot find a contract named ${args.contractName} in swanky.config.json` ); } diff --git a/src/commands/contract/new.ts b/src/commands/contract/new.ts index 0547f2eb..c671886f 100644 --- a/src/commands/contract/new.ts +++ b/src/commands/contract/new.ts @@ -1,13 +1,12 @@ import { Args, Flags } from "@oclif/core"; import path from "node:path"; -import { ensureDir, pathExists, pathExistsSync } from "fs-extra/esm"; +import { ensureDir, pathExists, pathExistsSync, writeJSON } from "fs-extra/esm"; import { checkCliDependencies, copyContractTemplateFiles, processTemplates, getTemplates, prepareTestFiles, - getSwankyConfig, } from "../../lib/index.js"; import { email, name, pickTemplate } from "../../lib/prompts.js"; import { paramCase, pascalCase, snakeCase } from "change-case"; @@ -15,7 +14,6 @@ import { execaCommandSync } from "execa"; import inquirer from "inquirer"; import { SwankyCommand } from "../../lib/swankyCommand.js"; import { InputError } from "../../lib/errors.js"; -import { ConfigBuilder } from "../../lib/config-builder.js"; export class NewContract extends SwankyCommand { static description = "Generate a new smart contract template inside a project"; @@ -110,10 +108,13 @@ export class NewContract extends SwankyCommand { await ensureDir(path.resolve(projectPath, "artifacts", args.contractName)); await this.spinner.runCommand(async () => { - const newLocalConfig = new ConfigBuilder(getSwankyConfig("local")) - .addContract(args.contractName) - .build(); - await this.storeConfig(newLocalConfig, "local"); + this.swankyConfig.contracts[args.contractName] = { + name: args.contractName, + moduleName: snakeCase(args.contractName), + deployments: [], + }; + + await writeJSON(path.resolve("swanky.config.json"), this.swankyConfig, { spaces: 2 }); }, "Writing config"); this.log("😎 New contract successfully generated! 😎"); diff --git a/src/commands/contract/query.ts b/src/commands/contract/query.ts index 0442c1e5..b094103c 100644 --- a/src/commands/contract/query.ts +++ b/src/commands/contract/query.ts @@ -6,15 +6,13 @@ export class Query extends ContractCall { static args = { ...ContractCall.callArgs }; - static flags = { ...ContractCall.callFlags }; - public async run(): Promise { const { flags, args } = await this.parse(Query); const contract = new ContractPromise( this.api.apiInst, this.metadata, - this.deploymentInfo.address, + this.deploymentInfo.address ); const storageDepositLimit = null; @@ -29,7 +27,7 @@ export class Query extends ContractCall { gasLimit, storageDepositLimit, }, - ...flags.params, + ...flags.params ); await this.api.apiInst.disconnect(); diff --git a/src/commands/contract/test.ts b/src/commands/contract/test.ts index 29bd6e6a..3ef72bfe 100644 --- a/src/commands/contract/test.ts +++ b/src/commands/contract/test.ts @@ -9,7 +9,7 @@ import { Contract } from "../../lib/contract.js"; import { SwankyCommand } from "../../lib/swankyCommand.js"; import { ConfigError, FileError, InputError, ProcessError, TestError } from "../../lib/errors.js"; import { spawn } from "node:child_process"; -import { configName, Spinner } from "../../lib/index.js"; +import { Spinner } from "../../lib/index.js"; declare global { var contractTypesPath: string; // eslint-disable-line no-var @@ -55,7 +55,7 @@ export class TestContract extends SwankyCommand { const contractRecord = this.swankyConfig.contracts[contractName]; if (!contractRecord) { throw new ConfigError( - `Cannot find a contract named ${args.contractName} in "${configName()}"` + `Cannot find a contract named ${args.contractName} in swanky.config.json` ); } diff --git a/src/commands/contract/tx.ts b/src/commands/contract/tx.ts index dbe13ce0..b7153789 100644 --- a/src/commands/contract/tx.ts +++ b/src/commands/contract/tx.ts @@ -12,7 +12,11 @@ export class Tx extends ContractCall { char: "d", description: "Do a dry run, without signing the transaction", }), - ...ContractCall.callFlags, + account: Flags.string({ + required: true, + char: "a", + description: "Account to sign the transaction with", + }), }; static args = { ...ContractCall.callArgs }; diff --git a/src/commands/contract/verify.ts b/src/commands/contract/verify.ts index a0d4b85f..e6ea3991 100644 --- a/src/commands/contract/verify.ts +++ b/src/commands/contract/verify.ts @@ -1,12 +1,10 @@ import { Args, Flags } from "@oclif/core"; import path from "node:path"; -import { ensureCargoContractVersionCompatibility, extractCargoContractVersion, getSwankyConfig, Spinner } from "../../lib/index.js"; +import { ensureCargoContractVersionCompatibility, extractCargoContractVersion, Spinner } from "../../lib/index.js"; import { pathExists } from "fs-extra/esm"; import { SwankyCommand } from "../../lib/swankyCommand.js"; import { ConfigError, InputError, ProcessError } from "../../lib/errors.js"; import { spawn } from "node:child_process"; -import { ConfigBuilder } from "../../lib/config-builder.js"; -import { BuildData, SwankyConfig } from "../../index.js"; export class VerifyContract extends SwankyCommand { static description = "Verify the smart contract(s) in your contracts directory"; @@ -31,8 +29,6 @@ export class VerifyContract extends SwankyCommand { async run(): Promise { const { args, flags } = await this.parse(VerifyContract); - const localConfig = getSwankyConfig("local") as SwankyConfig; - const cargoContractVersion = extractCargoContractVersion(); if (cargoContractVersion === null) throw new InputError( @@ -116,20 +112,11 @@ export class VerifyContract extends SwankyCommand { `Verifying ${contractName} contract`, `${contractName} Contract verified successfully` ); + contractInfo.build.isVerified = true; - await this.spinner.runCommand(async () => { - const buildData = { - ...contractInfo.build, - isVerified: true - } as BuildData; - - const newLocalConfig = new ConfigBuilder(localConfig) - .addContractBuild(args.contractName, buildData) - .build(); - - await this.storeConfig(newLocalConfig, "local"); - }, "Writing config"); + this.swankyConfig.contracts[contractName] = contractInfo; + await this.storeConfig(); } } } diff --git a/src/commands/generate/types.ts b/src/commands/generate/types.ts index a6c0ed24..79cf6134 100644 --- a/src/commands/generate/types.ts +++ b/src/commands/generate/types.ts @@ -1,5 +1,5 @@ import { Args } from "@oclif/core"; -import { configName, generateTypes } from "../../lib/index.js"; +import { generateTypes } from "../../lib/index.js"; import { Contract } from "../../lib/contract.js"; import { SwankyCommand } from "../../lib/swankyCommand.js"; import { ConfigError, FileError } from "../../lib/errors.js"; @@ -21,7 +21,7 @@ export class GenerateTypes extends SwankyCommand { const contractRecord = this.swankyConfig.contracts[args.contractName]; if (!contractRecord) { throw new ConfigError( - `Cannot find a contract named ${args.contractName} in "${configName()}"`, + `Cannot find a contract named ${args.contractName} in swanky.config.json` ); } @@ -29,7 +29,7 @@ export class GenerateTypes extends SwankyCommand { if (!(await contract.pathExists())) { throw new FileError( - `Path to contract ${args.contractName} does not exist: ${contract.contractPath}`, + `Path to contract ${args.contractName} does not exist: ${contract.contractPath}` ); } @@ -37,7 +37,7 @@ export class GenerateTypes extends SwankyCommand { if (!artifactsCheck.result) { throw new FileError( - `No artifact file found at path: ${artifactsCheck.missingPaths.toString()}`, + `No artifact file found at path: ${artifactsCheck.missingPaths.toString()}` ); } diff --git a/src/commands/init/index.ts b/src/commands/init/index.ts index 6a2ed7a7..a8915be3 100644 --- a/src/commands/init/index.ts +++ b/src/commands/init/index.ts @@ -8,7 +8,7 @@ import inquirer from "inquirer"; import TOML from "@iarna/toml"; import { choice, email, name, pickNodeVersion, pickTemplate } from "../../lib/prompts.js"; import { - buildSwankyConfig, + ChainAccount, checkCliDependencies, copyCommonTemplateFiles, copyContractTemplateFiles, @@ -19,14 +19,20 @@ import { processTemplates, swankyNodeVersions } from "../../lib/index.js"; +import { + ALICE_URI, BOB_URI, + DEFAULT_ASTAR_NETWORK_URL, + DEFAULT_NETWORK_URL, DEFAULT_NODE_INFO, + DEFAULT_SHIBUYA_NETWORK_URL, + DEFAULT_SHIDEN_NETWORK_URL, +} from "../../lib/consts.js"; import { SwankyCommand } from "../../lib/swankyCommand.js"; import { InputError, UnknownError } from "../../lib/errors.js"; import { globby, GlobEntry } from "globby"; import { merge } from "lodash-es"; import inquirerFuzzyPath from "inquirer-fuzzy-path"; +import { SwankyConfig } from "../../types/index.js"; import chalk from "chalk"; -import { ConfigBuilder } from "../../lib/config-builder.js"; -import { DEFAULT_NODE_INFO } from "../../lib/consts.js"; type TaskFunction = (...args: any[]) => any; @@ -90,9 +96,25 @@ export class Init extends SwankyCommand { projectPath = ""; - taskQueue: Task[] = []; - configBuilder = new ConfigBuilder(buildSwankyConfig()); + configBuilder: Partial = { + node: { + localPath: "", + polkadotPalletVersions: "", + supportedInk: "", + version: "", + }, + accounts: [], + networks: { + local: { url: DEFAULT_NETWORK_URL }, + astar: { url: DEFAULT_ASTAR_NETWORK_URL }, + shiden: { url: DEFAULT_SHIDEN_NETWORK_URL }, + shibuya: { url: DEFAULT_SHIBUYA_NETWORK_URL }, + }, + contracts: {}, + }; + + taskQueue: Task[] = []; async run(): Promise { const { args, flags } = await this.parse(Init); @@ -158,23 +180,44 @@ export class Init extends SwankyCommand { task: downloadNode, args: [this.projectPath, nodeInfo, this.spinner], runningMessage: "Downloading Swanky node", - callback: (localPath) => this.configBuilder.updateNodeSettings({ supportedInk: nodeInfo.supportedInk, - polkadotPalletVersions: nodeInfo.polkadotPalletVersions, - version: nodeInfo.version, localPath }), + callback: (result) => { + this.configBuilder.node = { + supportedInk: nodeInfo.supportedInk, + polkadotPalletVersions: nodeInfo.polkadotPalletVersions, + version: nodeInfo.version, + localPath: result, + }; + } }); } } - Object.keys(this.swankyConfig.contracts).forEach(async (contractName) => { + this.configBuilder.accounts = [ + { + alias: "alice", + mnemonic: ALICE_URI, + isDev: true, + address: new ChainAccount(ALICE_URI).pair.address, + }, + { + alias: "bob", + mnemonic: BOB_URI, + isDev: true, + address: new ChainAccount(BOB_URI).pair.address, + }, + ]; + + Object.keys(this.configBuilder.contracts!).forEach(async (contractName) => { await ensureDir(path.resolve(this.projectPath, "artifacts", contractName)); }); this.taskQueue.push({ - task: async () => - await this.storeConfig(this.configBuilder.build(), "local", this.projectPath), + task: () => + writeJSON(path.resolve(this.projectPath, "swanky.config.json"), this.configBuilder, { + spaces: 2, + }), args: [], runningMessage: "Writing config", - shouldExitOnError: true, }); for (const { @@ -271,13 +314,13 @@ export class Init extends SwankyCommand { runningMessage: "Processing templates", }); - this.configBuilder.updateContracts( { + this.configBuilder.contracts = { [contractName as string]: { name: contractName, moduleName: snakeCase(contractName), deployments: [], }, - }); + }; } async convert(pathToExistingProject: string, projectName: string) { @@ -347,8 +390,14 @@ export class Init extends SwankyCommand { }, }); + if (!this.configBuilder.contracts) this.configBuilder.contracts = {}; + for (const contract of confirmedCopyList.contracts) { - this.configBuilder.addContract(contract.name, contract.moduleName); + this.configBuilder.contracts[contract.name] = { + name: contract.name, + moduleName: contract.moduleName!, + deployments: [], + }; } let rootToml = await readRootCargoToml(pathToExistingProject); diff --git a/src/commands/node/install.ts b/src/commands/node/install.ts index 9af510e1..79beab3e 100644 --- a/src/commands/node/install.ts +++ b/src/commands/node/install.ts @@ -1,9 +1,9 @@ import { SwankyCommand } from "../../lib/swankyCommand.js"; import { Flags } from "@oclif/core"; -import { downloadNode, getSwankyConfig, swankyNodeVersions } from "../../lib/index.js"; +import { downloadNode, swankyNodeVersions } from "../../lib/index.js"; import path from "node:path"; +import { writeJSON } from "fs-extra/esm"; import inquirer from "inquirer"; -import { ConfigBuilder } from "../../lib/config-builder.js"; import { DEFAULT_NODE_INFO } from "../../lib/consts.js"; import { choice, pickNodeVersion } from "../../lib/prompts.js"; import { InputError } from "../../lib/errors.js"; @@ -55,19 +55,23 @@ export class InstallNode extends SwankyCommand { () => downloadNode(projectPath, nodeInfo, this.spinner), "Downloading Swanky node" )) as string; - const nodePath = path.resolve(projectPath, taskResult); + const nodePath = path.relative(projectPath, taskResult); - await this.spinner.runCommand(async () => { - const newLocalConfig = new ConfigBuilder(getSwankyConfig("local")) - .updateNodeSettings({ - localPath: nodePath, - polkadotPalletVersions: nodeInfo.polkadotPalletVersions, - supportedInk: nodeInfo.supportedInk, - version: nodeInfo.version, - }) - .build(); - await this.storeConfig(newLocalConfig, "local"); - }, "Updating swanky config"); + + this.swankyConfig.node = { + localPath: nodePath, + polkadotPalletVersions: nodeInfo.polkadotPalletVersions, + supportedInk: nodeInfo.supportedInk, + version: nodeInfo.version, + }; + + await this.spinner.runCommand( + () => + writeJSON(path.resolve(projectPath, "swanky.config.json"), this.swankyConfig, { + spaces: 2, + }), + "Updating swanky config" + ); this.log("Swanky Node Installed successfully"); } diff --git a/src/commands/node/start.ts b/src/commands/node/start.ts index 53a85590..e92e65e6 100644 --- a/src/commands/node/start.ts +++ b/src/commands/node/start.ts @@ -29,8 +29,9 @@ export class StartNode extends SwankyCommand { async run(): Promise { const { flags } = await this.parse(StartNode); - if(this.swankyConfig.node.localPath === "") { - this.error("Swanky node is not installed. Please run `swanky node:install` first."); + if (this.swankyConfig.node.version === "") { + this.log("Node is not installed"); + return; } // Run persistent mode by default. non-persistent mode in case flag is provided. // Non-Persistent mode (`--dev`) allows all CORS origin, without `--dev`, users need to specify origins by `--rpc-cors`. diff --git a/src/lib/command-utils.ts b/src/lib/command-utils.ts index 270ea732..4478b6ee 100644 --- a/src/lib/command-utils.ts +++ b/src/lib/command-utils.ts @@ -1,22 +1,9 @@ import { execaCommand, execaCommandSync } from "execa"; -import { copy, emptyDir, ensureDir, readJSONSync } from "fs-extra/esm"; +import { copy, emptyDir, ensureDir, readJSON } from "fs-extra/esm"; import path from "node:path"; -import { - DEFAULT_NETWORK_URL, - ARTIFACTS_PATH, - TYPED_CONTRACTS_PATH, - DEFAULT_SHIBUYA_NETWORK_URL, - DEFAULT_SHIDEN_NETWORK_URL, - DEFAULT_ASTAR_NETWORK_URL, - DEFAULT_ACCOUNT, - DEFAULT_CONFIG_NAME, - DEFAULT_CONFIG_FOLDER_NAME, - DEFAULT_NODE_INFO, -} from "./consts.js"; -import { SwankyConfig, SwankySystemConfig } from "../types/index.js"; -import { ConfigError, FileError } from "./errors.js"; -import { userInfo } from "os"; -import { existsSync } from "fs"; +import { DEFAULT_NETWORK_URL, ARTIFACTS_PATH, TYPED_CONTRACTS_PATH } from "./consts.js"; +import { SwankyConfig } from "../types/index.js"; +import { ConfigError, FileError, InputError } from "./errors.js"; export function commandStdoutOrNull(command: string): string | null { try { @@ -27,24 +14,13 @@ export function commandStdoutOrNull(command: string): string | null { } } -export function getSwankyConfig(configType: "local" | "global"): SwankyConfig | SwankySystemConfig { - let configPath: string; - - if (configType === "global") { - configPath = getSystemConfigDirectoryPath() + `/${DEFAULT_CONFIG_NAME}`; - } else { - configPath = isEnvConfigCheck() ? process.env.SWANKY_CONFIG! : DEFAULT_CONFIG_NAME; +export async function getSwankyConfig(): Promise { + try { + const config = await readJSON("swanky.config.json"); + return config; + } catch (cause) { + throw new InputError("Error reading swanky.config.json in the current directory!", { cause }); } - - const config = readJSONSync(configPath); - return config; -} - - -export function getSystemConfigDirectoryPath(): string { - const homeDir = userInfo().homedir; - const configPath = homeDir + `/${DEFAULT_CONFIG_FOLDER_NAME}`; - return configPath; } export function resolveNetworkUrl(config: SwankyConfig, networkName: string): string { @@ -144,66 +120,3 @@ export async function generateTypes(contractName: string) { `npx typechain-polkadot --in ${relativeInputPath} --out ${relativeOutputPath}` ); } -export function ensureAccountIsSet(account: string | undefined, config: SwankyConfig) { - if(!account && config.defaultAccount === null) { - throw new ConfigError("No default account set. Please set one or provide an account alias with --account"); - } -} - -export function buildSwankyConfig() { - return { - node: { - localPath: "", - polkadotPalletVersions: DEFAULT_NODE_INFO.polkadotPalletVersions, - supportedInk: DEFAULT_NODE_INFO.supportedInk, - version: DEFAULT_NODE_INFO.version, - }, - defaultAccount: DEFAULT_ACCOUNT, - accounts: [ - { - "alias": "alice", - "mnemonic": "//Alice", - "isDev": true, - "address": "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY" - }, - { - "alias": "bob", - "mnemonic": "//Bob", - "isDev": true, - "address": "5FHneW46xGXgs5mUiveU4sbTyGBzmstUspZC92UhjJM694ty" - }, - ], - networks: { - local: { url: DEFAULT_NETWORK_URL }, - astar: { url: DEFAULT_ASTAR_NETWORK_URL }, - shiden: { url: DEFAULT_SHIDEN_NETWORK_URL }, - shibuya: { url: DEFAULT_SHIBUYA_NETWORK_URL }, - }, - contracts: {}, - }; -} - -export function isEnvConfigCheck(): boolean { - if (process.env.SWANKY_CONFIG === undefined) { - return false; - } else if (existsSync(process.env.SWANKY_CONFIG)) { - return true; - } else { - throw new ConfigError(`Provided config path ${process.env.SWANKY_CONFIG} does not exist`); - } -} - -export function isLocalConfigCheck(): boolean { - const defaultLocalConfigPath = process.cwd() + `/${DEFAULT_CONFIG_NAME}`; - return process.env.SWANKY_CONFIG === undefined - ? existsSync(defaultLocalConfigPath) - : existsSync(process.env.SWANKY_CONFIG); -} - -export function configName(): string { - if (!isLocalConfigCheck()) { - return DEFAULT_CONFIG_NAME + " [system config]"; - } - - return process.env.SWANKY_CONFIG?.split("/").pop() ?? DEFAULT_CONFIG_NAME; -} \ No newline at end of file diff --git a/src/lib/config-builder.ts b/src/lib/config-builder.ts deleted file mode 100644 index ace3fccd..00000000 --- a/src/lib/config-builder.ts +++ /dev/null @@ -1,70 +0,0 @@ -import { AccountData, BuildData, DeploymentData, SwankyConfig, SwankySystemConfig } from "../index.js"; -import { snakeCase } from "change-case"; - -export class ConfigBuilder { - private config: T; - - constructor(existingConfig: T) { - this.config = { ...existingConfig }; - } - - setDefaultAccount(account: string): ConfigBuilder { - this.config.defaultAccount = account; - return this; - } - - addAccount(account: AccountData): ConfigBuilder { - this.config.accounts.push(account); - return this; - } - - updateNetwork(name: string, url: string): ConfigBuilder { - if (this.config.networks?.[name]) { - this.config.networks[name].url = url; - } - return this; - } - - updateNodeSettings(nodeSettings: Partial): ConfigBuilder { - if ("node" in this.config) { - this.config.node = { ...this.config.node, ...nodeSettings }; - } - return this; - } - - updateContracts(contracts: SwankyConfig["contracts"]): ConfigBuilder { - if ("contracts" in this.config) { - this.config.contracts = { ...contracts }; - } - return this; - } - - addContract(name: string, moduleName?: string): ConfigBuilder { - if ("contracts" in this.config) { - this.config.contracts[name] = { - name: name, - moduleName: moduleName ?? snakeCase(name), - deployments: [], - }; - } - return this; - } - - addContractDeployment(name: string, data: DeploymentData): ConfigBuilder { - if ("contracts" in this.config) { - this.config.contracts[name].deployments.push(data); - } - return this; - } - - addContractBuild(name: string, data: BuildData): ConfigBuilder { - if ("contracts" in this.config) { - this.config.contracts[name].build = data; - } - return this; - } - - build(): T { - return this.config; - } -} diff --git a/src/lib/consts.ts b/src/lib/consts.ts index 8883913b..b9391283 100644 --- a/src/lib/consts.ts +++ b/src/lib/consts.ts @@ -7,10 +7,6 @@ export const DEFAULT_ASTAR_NETWORK_URL = "wss://rpc.astar.network"; export const DEFAULT_SHIDEN_NETWORK_URL = "wss://rpc.shiden.astar.network"; export const DEFAULT_SHIBUYA_NETWORK_URL = "wss://shibuya.public.blastapi.io"; -export const DEFAULT_ACCOUNT = "alice"; -export const DEFAULT_CONFIG_FOLDER_NAME = "swanky"; -export const DEFAULT_CONFIG_NAME = "swanky.config.json"; - export const ARTIFACTS_PATH = "artifacts"; export const TYPED_CONTRACTS_PATH = "typedContracts"; diff --git a/src/lib/contractCall.ts b/src/lib/contractCall.ts index a65f4894..9c9e0b2f 100644 --- a/src/lib/contractCall.ts +++ b/src/lib/contractCall.ts @@ -1,4 +1,4 @@ -import { AbiType, ChainAccount, ChainApi, configName, ensureAccountIsSet, decrypt, resolveNetworkUrl } from "./index.js"; +import { AbiType, ChainAccount, ChainApi, decrypt, resolveNetworkUrl } from "./index.js"; import { ContractData, DeploymentData, Encrypted } from "../types/index.js"; import { Args, Command, Flags, Interfaces } from "@oclif/core"; import inquirer from "inquirer"; @@ -28,14 +28,6 @@ export abstract class ContractCall extends SwankyComma }), }; - static callFlags = { - network: Flags.string({ - char: "n", - default: "local", - description: "Name of network to connect to", - }), - } - protected flags!: JoinedFlagsType; protected args!: Record; protected contractInfo!: ContractData; @@ -48,12 +40,11 @@ export abstract class ContractCall extends SwankyComma await super.init(); const { flags, args } = await this.parse(this.ctor); this.args = args; - this.flags = flags as JoinedFlagsType; const contractRecord = this.swankyConfig.contracts[args.contractName]; if (!contractRecord) { throw new ConfigError( - `Cannot find a contract named ${args.contractName} in "${configName()}"`, + `Cannot find a contract named ${args.contractName} in swanky.config.json` ); } @@ -61,7 +52,7 @@ export abstract class ContractCall extends SwankyComma if (!(await contract.pathExists())) { throw new FileError( - `Path to contract ${args.contractName} does not exist: ${contract.contractPath}`, + `Path to contract ${args.contractName} does not exist: ${contract.contractPath}` ); } @@ -69,32 +60,24 @@ export abstract class ContractCall extends SwankyComma if (!artifactsCheck.result) { throw new FileError( - `No artifact file found at path: ${artifactsCheck.missingPaths.toString()}`, + `No artifact file found at path: ${artifactsCheck.missingPaths.toString()}` ); } const deploymentData = flags.address ? contract.deployments.find( - (deployment: DeploymentData) => deployment.address === flags.address, - ) + (deployment: DeploymentData) => deployment.address === flags.address + ) : contract.deployments[0]; if (!deploymentData?.address) throw new NetworkError( - `Cannot find a deployment with address: ${flags.address} in "${configName()}"`, + `Cannot find a deployment with address: ${flags.address} in swanky.config.json` ); this.deploymentInfo = deploymentData; - ensureAccountIsSet(flags.account, this.swankyConfig); - - const accountAlias = flags.account ?? this.swankyConfig.defaultAccount; const accountData = this.findAccountByAlias(flags.account || "alice"); - - if (accountData.isDev && (flags.network !== "local" || !flags.network)) { - throw new ConfigError(`Account ${chalk.redBright(accountAlias)} is a dev account and can only be used on the local network`); - } - const networkUrl = resolveNetworkUrl(this.swankyConfig, flags.network ?? ""); const api = await ChainApi.create(networkUrl); this.api = api; @@ -103,17 +86,17 @@ export abstract class ContractCall extends SwankyComma const mnemonic = accountData.isDev ? (accountData.mnemonic as string) : decrypt( - accountData.mnemonic as Encrypted, - ( - await inquirer.prompt([ - { - type: "password", - message: `Enter password for ${chalk.yellowBright(accountData.alias)}: `, - name: "password", - }, - ]) - ).password, - ); + accountData.mnemonic as Encrypted, + ( + await inquirer.prompt([ + { + type: "password", + message: `Enter password for ${chalk.yellowBright(accountData.alias)}: `, + name: "password", + }, + ]) + ).password + ); const account = (await this.spinner.runCommand(async () => { await cryptoWaitReady(); @@ -160,7 +143,7 @@ ContractCall.baseFlags = { }), account: Flags.string({ char: "a", - description: "Account alias to sign the transaction with", + description: "Account to sign the transaction with", }), address: Flags.string({ required: false, diff --git a/src/lib/swankyCommand.ts b/src/lib/swankyCommand.ts index a184cb86..4f2b5a73 100644 --- a/src/lib/swankyCommand.ts +++ b/src/lib/swankyCommand.ts @@ -1,18 +1,11 @@ import { Command, Flags, Interfaces } from "@oclif/core"; import chalk from "chalk"; -import { buildSwankyConfig, - configName, - getSwankyConfig, - getSystemConfigDirectoryPath, Spinner } from "./index.js"; -import { AccountData, SwankyConfig, SwankySystemConfig } from "../types/index.js"; +import { getSwankyConfig, Spinner } from "./index.js"; +import { AccountData, SwankyConfig } from "../types/index.js"; import { writeJSON } from "fs-extra/esm"; -import { existsSync, mkdirSync } from "fs"; import { BaseError, ConfigError, UnknownError } from "./errors.js"; import { swankyLogger } from "./logger.js"; import { Logger } from "winston"; -import path from "node:path"; -import { DEFAULT_CONFIG_FOLDER_NAME, DEFAULT_CONFIG_NAME } from "./consts.js"; - export type Flags = Interfaces.InferredFlags< (typeof SwankyCommand)["baseFlags"] & T["flags"] >; @@ -38,14 +31,20 @@ export abstract class SwankyCommand extends Command { args: this.ctor.args, strict: this.ctor.strict, }); - this.flags = flags as Flags; this.args = args as Args; this.logger = swankyLogger; - this.swankyConfig = buildSwankyConfig(); - - await this.loadAndMergeConfig(); + try { + this.swankyConfig = await getSwankyConfig(); + } catch (error) { + if ( + error instanceof Error && + error.message.includes("swanky.config.json") && + (this.constructor as typeof SwankyCommand).ENSURE_SWANKY_CONFIG + ) + throw new ConfigError("Cannot find swanky.config.json", { cause: error }); + } this.logger.info(`Running command: ${this.ctor.name} Args: ${JSON.stringify(this.args)} @@ -53,91 +52,6 @@ export abstract class SwankyCommand extends Command { Full command: ${JSON.stringify(process.argv)}`); } - protected async loadAndMergeConfig(): Promise { - try { - const systemConfig = getSwankyConfig("global"); - this.swankyConfig = { ...this.swankyConfig, ...systemConfig }; - } catch (error) { - this.warn( - `No Swanky system config found; creating one in "/${DEFAULT_CONFIG_FOLDER_NAME}/${DEFAULT_CONFIG_NAME}}" at home directory` - ); - await this.storeConfig(this.swankyConfig, "global"); - } - - try { - const localConfig = getSwankyConfig("local") as SwankyConfig; - this.mergeAccountsWithExistingConfig(this.swankyConfig, localConfig); - const originalDefaultAccount = this.swankyConfig.defaultAccount; - this.swankyConfig = { ...this.swankyConfig, ...localConfig }; - this.swankyConfig.defaultAccount = localConfig.defaultAccount ?? originalDefaultAccount; - } catch (error) { - this.handleLocalConfigError(error); - } - } - - private handleLocalConfigError(error: unknown): void { - this.logger.warn("No local config found"); - if ( - error instanceof Error && - error.message.includes(configName()) && - (this.constructor as typeof SwankyCommand).ENSURE_SWANKY_CONFIG - ) { - throw new ConfigError(`Cannot find ${process.env.SWANKY_CONFIG ?? DEFAULT_CONFIG_NAME}`, { - cause: error, - }); - } - } - - protected async storeConfig( - newConfig: SwankyConfig | SwankySystemConfig, - configType: "local" | "global", - projectPath?: string - ) { - let configPath: string; - - if (configType === "local") { - configPath = - process.env.SWANKY_CONFIG ?? - path.resolve(projectPath ?? process.cwd(), DEFAULT_CONFIG_NAME); - } else { - // global - configPath = getSystemConfigDirectoryPath() + `/${DEFAULT_CONFIG_NAME}`; - if ("node" in newConfig) { - // If it's a SwankyConfig, extract only the system relevant parts for the global SwankySystemConfig config - newConfig = { - defaultAccount: newConfig.defaultAccount, - accounts: newConfig.accounts, - networks: newConfig.networks, - }; - } - if (existsSync(configPath)) { - const systemConfig = getSwankyConfig("global"); - this.mergeAccountsWithExistingConfig(systemConfig, newConfig); - } - } - - this.ensureDirectoryExists(configPath); - await writeJSON(configPath, newConfig, { spaces: 2 }); - } - - private ensureDirectoryExists(filePath: string) { - const directory = path.dirname(filePath); - if (!existsSync(directory)) { - mkdirSync(directory, { recursive: true }); - } - } - - private mergeAccountsWithExistingConfig( - existingConfig: SwankySystemConfig | SwankyConfig, - newConfig: SwankySystemConfig - ) { - const accountMap = new Map( - [...existingConfig.accounts, ...newConfig.accounts].map((account) => [account.alias, account]) - ); - - newConfig.accounts = Array.from(accountMap.values()); - } - protected findAccountByAlias(alias: string): AccountData { const accountData = this.swankyConfig.accounts.find( (account: AccountData) => account.alias === alias @@ -150,6 +64,10 @@ export abstract class SwankyCommand extends Command { return accountData; } + protected async storeConfig() { + await writeJSON("swanky.config.json", this.swankyConfig, { spaces: 2 }); + } + protected async catch(err: Error & { exitCode?: number }): Promise { // add any custom logic to handle errors from the command // or simply return the parent class error handling diff --git a/src/types/index.ts b/src/types/index.ts index 8e0af423..0dab9358 100644 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -24,7 +24,7 @@ export interface ContractData { name: string; moduleName: string; build?: BuildData; - deployments: DeploymentData[]; + deployments: DeploymentData[] | []; } export interface BuildData { @@ -40,19 +40,15 @@ export interface DeploymentData { deployerAlias: string; address: string; } -export interface SwankyConfig extends SwankySystemConfig{ +export interface SwankyConfig { node: { polkadotPalletVersions: string; localPath: string; supportedInk: string; version: string; }; - contracts: Record | Record; -} - -export interface SwankySystemConfig { - defaultAccount: string | null; accounts: AccountData[]; + contracts: Record | Record; networks: Record }