Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: refactor ensure checks to avoid code duplication #215

Merged
merged 3 commits into from
Mar 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 3 additions & 4 deletions src/commands/clear/index.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { SwankyCommand } from "../../lib/swankyCommand.js";
import { ConfigError, FileError } from "../../lib/errors.js";
import { FileError } from "../../lib/errors.js";
import fs from "fs-extra";
import path from "node:path";
import { Args, Flags } from "@oclif/core";
import { ensureContractNameOrAllFlagIsSet } from "../../lib/checks.js";

interface Folder {
name: string,
Expand Down Expand Up @@ -44,9 +45,7 @@ export default class Clear extends SwankyCommand<typeof Clear> {

const { flags, args } = await this.parse(Clear);

if (args.contractName === undefined && !flags.all) {
throw new ConfigError("Specify a contract name or use the --all flag to delete all artifacts.");
}
ensureContractNameOrAllFlagIsSet(args, flags);

const workDirectory = process.cwd();
const foldersToDelete: Folder[] = flags.all ?
Expand Down
34 changes: 15 additions & 19 deletions src/commands/contract/compile.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,17 @@
import { Args, Flags } from "@oclif/core";
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 { ConfigError, InputError, ProcessError } from "../../lib/errors.js";
import {
extractCargoContractVersion,
Spinner,
storeArtifacts,
getSwankyConfig,
findContractRecord,
} from "../../lib/index.js";
import { InputError, ProcessError } from "../../lib/errors.js";
import { BuildMode, SwankyConfig } from "../../index.js";
import { ConfigBuilder } from "../../lib/config-builder.js";
import { ensureContractNameOrAllFlagIsSet, ensureContractPathExists, ensureCargoContractVersionCompatibility, } from "../../lib/checks.js";

export class CompileContract extends SwankyCommand<typeof CompileContract> {
static description = "Compile the smart contract(s) in your contracts directory";
Expand Down Expand Up @@ -44,9 +49,7 @@ export class CompileContract extends SwankyCommand<typeof 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 } });
}
ensureContractNameOrAllFlagIsSet(args, flags);

const contractNames = flags.all
? Object.keys(this.swankyConfig.contracts)
Expand All @@ -55,17 +58,10 @@ export class CompileContract extends SwankyCommand<typeof CompileContract> {

for (const contractName of contractNames) {
this.logger.info(`Started compiling contract [${contractName}]`);
const contractInfo = this.swankyConfig.contracts[contractName];
if (!contractInfo) {
throw new ConfigError(
`Cannot find contract info for ${contractName} contract in "${configName()}"`
);
}
const contractPath = path.resolve("contracts", contractInfo.name);
this.logger.info(`"Looking for contract ${contractInfo.name} in path: [${contractPath}]`);
if (!(await pathExists(contractPath))) {
throw new InputError(`Contract folder not found at expected path`);
}

const contractRecord = findContractRecord(this.swankyConfig, contractName);

await ensureContractPathExists(contractName);

let buildMode = BuildMode.Debug;
const compilationResult = await spinner.runCommand(
Expand Down Expand Up @@ -130,7 +126,7 @@ export class CompileContract extends SwankyCommand<typeof CompileContract> {
const artifactsPath = compilationResult as string;

await spinner.runCommand(async () => {
return storeArtifacts(artifactsPath, contractInfo.name, contractInfo.moduleName);
return storeArtifacts(artifactsPath, contractRecord.name, contractRecord.moduleName);
}, "Moving artifacts");

await this.spinner.runCommand(async () => {
Expand Down
49 changes: 17 additions & 32 deletions src/commands/contract/deploy.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,22 @@
import { Args, Flags } from "@oclif/core";
import { cryptoWaitReady } from "@polkadot/util-crypto/crypto";
import { AbiType, ChainAccount, ChainApi, decrypt, resolveNetworkUrl, ensureAccountIsSet, configName, getSwankyConfig } from "../../lib/index.js";
import {
AbiType,
ChainAccount,
ChainApi,
decrypt,
resolveNetworkUrl,
ensureAccountIsSet,
getSwankyConfig,
findContractRecord,
} from "../../lib/index.js";
import { BuildMode, Encrypted, SwankyConfig } 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 { ApiError, ProcessError } from "../../lib/errors.js";
import { ConfigBuilder } from "../../lib/config-builder.js";
import { contractFromRecord, ensureArtifactsExist, ensureDevAccountNotInProduction } from "../../lib/checks.js";

export class DeployContract extends SwankyCommand<typeof DeployContract> {
static description = "Deploy contract to a running node";
Expand Down Expand Up @@ -47,28 +56,12 @@ export class DeployContract extends SwankyCommand<typeof DeployContract> {
const { args, flags } = await this.parse(DeployContract);

const localConfig = getSwankyConfig("local") as SwankyConfig;
const contractRecord = localConfig.contracts[args.contractName];
if (!contractRecord) {
throw new ConfigError(
`Cannot find a contract named ${args.contractName} in "${configName()}"`
);
}

const contract = new Contract(contractRecord);
const contractRecord = findContractRecord(localConfig, args.contractName);

if (!(await contract.pathExists())) {
throw new FileError(
`Path to contract ${args.contractName} does not exist: ${contract.contractPath}`
);
}
const contract = (await contractFromRecord(contractRecord));

const artifactsCheck = await contract.artifactsExist();

if (!artifactsCheck.result) {
throw new FileError(
`No artifact file found at path: ${artifactsCheck.missingPaths.toString()}`
);
}
await ensureArtifactsExist(contract);

if (contract.buildMode === undefined) {
throw new ProcessError(
Expand Down Expand Up @@ -99,19 +92,11 @@ export class DeployContract extends SwankyCommand<typeof DeployContract> {

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 accountAlias = (flags.account ?? this.swankyConfig.defaultAccount)!;

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`
);
}
ensureDevAccountNotInProduction(accountData, flags.network);

const mnemonic = accountData.isDev
? (accountData.mnemonic as string)
Expand Down
28 changes: 5 additions & 23 deletions src/commands/contract/explain.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
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";
import { findContractRecord } from "../../lib/index.js";
import { contractFromRecord, ensureArtifactsExist } from "../../lib/checks.js";

export class ExplainContract extends SwankyCommand<typeof ExplainContract> {
static description = "Explain contract messages based on the contracts' metadata";
Expand All @@ -18,28 +17,11 @@ export class ExplainContract extends SwankyCommand<typeof ExplainContract> {
async run(): Promise<void> {
const { args } = await this.parse(ExplainContract);

const contractRecord = this.swankyConfig.contracts[args.contractName];
if (!contractRecord) {
throw new ConfigError(
`Cannot find a contract named ${args.contractName} in "${configName()}"`
);
}
const contractRecord = findContractRecord(this.swankyConfig, args.contractName);

const contract = new Contract(contractRecord);
const contract = (await contractFromRecord(contractRecord));

if (!(await contract.pathExists())) {
throw new FileError(
`Path to contract ${args.contractName} does not exist: ${contract.contractPath}`
);
}

const artifactsCheck = await contract.artifactsExist();

if (!artifactsCheck.result) {
throw new FileError(
`No artifact file found at path: ${artifactsCheck.missingPaths.toString()}`
);
}
await ensureArtifactsExist(contract);

await contract.printInfo();
}
Expand Down
4 changes: 2 additions & 2 deletions src/commands/contract/new.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import {
processTemplates,
getTemplates,
prepareTestFiles,
getSwankyConfig,
getSwankyConfig, configName,
} from "../../lib/index.js";
import { email, name, pickTemplate } from "../../lib/prompts.js";
import { kebabCase, pascalCase, snakeCase } from "change-case";
Expand Down Expand Up @@ -45,7 +45,7 @@ export class NewContract extends SwankyCommand<typeof NewContract> {

if (this.swankyConfig.contracts[args.contractName]) {
throw new InputError(
`Contract with a name '${args.contractName}' already exists in swanky.config`
`Contract with a name '${args.contractName}' already exists in ${configName()}`
);
}

Expand Down
48 changes: 13 additions & 35 deletions src/commands/contract/test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,15 @@ import Mocha from "mocha";
import { emptyDir, pathExistsSync } from "fs-extra/esm";
import { Contract } from "../../lib/contract.js";
import { SwankyCommand } from "../../lib/swankyCommand.js";
import { ConfigError, FileError, InputError, ProcessError, TestError } from "../../lib/errors.js";
import { FileError, ProcessError, TestError } from "../../lib/errors.js";
import { spawn } from "node:child_process";
import { configName, Spinner } from "../../lib/index.js";
import { findContractRecord, Spinner } from "../../lib/index.js";
import {
contractFromRecord,
ensureArtifactsExist,
ensureContractNameOrAllFlagIsSet,
ensureTypedContractExists,
} from "../../lib/checks.js";

declare global {
var contractTypesPath: string; // eslint-disable-line no-var
Expand Down Expand Up @@ -40,9 +46,7 @@ export class TestContract extends SwankyCommand<typeof TestContract> {
async run(): Promise<void> {
const { args, flags } = await this.parse(TestContract);

if (args.contractName === undefined && !flags.all) {
throw new InputError("No contracts were selected to compile");
}
ensureContractNameOrAllFlagIsSet(args, flags);

const contractNames = flags.all
? Object.keys(this.swankyConfig.contracts)
Expand All @@ -51,20 +55,9 @@ export class TestContract extends SwankyCommand<typeof TestContract> {
const spinner = new Spinner();

for (const contractName of contractNames) {
const contractRecord = this.swankyConfig.contracts[contractName];
if (!contractRecord) {
throw new ConfigError(
`Cannot find a contract named ${args.contractName} in "${configName()}"`
);
}
const contractRecord = findContractRecord(this.swankyConfig, contractName);

const contract = new Contract(contractRecord);

if (!(await contract.pathExists())) {
throw new FileError(
`Path to contract ${args.contractName} does not exist: ${contract.contractPath}`
);
}
const contract = (await contractFromRecord(contractRecord));

console.log(`Testing contract: ${contractName}`);

Expand Down Expand Up @@ -125,24 +118,9 @@ export class TestContract extends SwankyCommand<typeof TestContract> {
throw new FileError(`Test directory does not exist: ${testDir}`);
}

const artifactsCheck = await contract.artifactsExist();

if (!artifactsCheck.result) {
throw new FileError(
`No artifact file found at path: ${artifactsCheck.missingPaths.toString()}`
);
}

const artifactPath = path.resolve("typedContracts", `${contract.name}`);
const typedContractCheck = await contract.typedContractExists(contract.name);

this.log(`artifactPath: ${artifactPath}`);
await ensureArtifactsExist(contract);

if (!typedContractCheck.result) {
throw new FileError(
`No typed contract found at path: ${typedContractCheck.missingPaths.toString()}`
);
}
await ensureTypedContractExists(contract);

const reportDir = path.resolve(testDir, "testReports");
await emptyDir(reportDir);
Expand Down
38 changes: 17 additions & 21 deletions src/commands/contract/verify.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
import { Args, Flags } from "@oclif/core";
import path from "node:path";
import { ensureCargoContractVersionCompatibility, extractCargoContractVersion, getSwankyConfig, Spinner } from "../../lib/index.js";
import { pathExists } from "fs-extra/esm";
import {
extractCargoContractVersion,
findContractRecord,
getSwankyConfig,
Spinner,
} from "../../lib/index.js";
import { SwankyCommand } from "../../lib/swankyCommand.js";
import { ConfigError, InputError, ProcessError } from "../../lib/errors.js";
import { 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";
import { ensureContractNameOrAllFlagIsSet, ensureContractPathExists, ensureCargoContractVersionCompatibility } from "../../lib/checks.js";

export class VerifyContract extends SwankyCommand<typeof VerifyContract> {
static description = "Verify the smart contract(s) in your contracts directory";
Expand Down Expand Up @@ -43,9 +47,7 @@ export class VerifyContract extends SwankyCommand<typeof VerifyContract> {
"4.0.0-alpha",
]);

if (args.contractName === undefined && !flags.all) {
throw new InputError("No contracts were selected to verify", { winston: { stack: true } });
}
ensureContractNameOrAllFlagIsSet(args, flags);

const contractNames = flags.all
? Object.keys(this.swankyConfig.contracts)
Expand All @@ -55,26 +57,20 @@ export class VerifyContract extends SwankyCommand<typeof VerifyContract> {

for (const contractName of contractNames) {
this.logger.info(`Started compiling contract [${contractName}]`);
const contractInfo = this.swankyConfig.contracts[contractName];
if (!contractInfo) {
throw new ConfigError(
`Cannot find contract info for ${contractName} contract in swanky.config.json`
);
}
const contractPath = path.resolve("contracts", contractInfo.name);
this.logger.info(`"Looking for contract ${contractInfo.name} in path: [${contractPath}]`);
if (!(await pathExists(contractPath))) {
throw new InputError(`Contract folder not found at expected path`);
}

if(!contractInfo.build) {
const contractRecord = findContractRecord(this.swankyConfig, contractName);

await ensureContractPathExists(contractName);


if(!contractRecord.build) {
throw new InputError(`Contract ${contractName} is not compiled. Please compile it first`);
}

await spinner.runCommand(
async () => {
return new Promise<boolean>((resolve, reject) => {
if(contractInfo.build!.isVerified) {
if(contractRecord.build!.isVerified) {
this.logger.info(`Contract ${contractName} is already verified`);
resolve(true);
}
Expand Down Expand Up @@ -119,7 +115,7 @@ export class VerifyContract extends SwankyCommand<typeof VerifyContract> {

await this.spinner.runCommand(async () => {
const buildData = {
...contractInfo.build,
...contractRecord.build,
isVerified: true
} as BuildData;

Expand Down
Loading
Loading