Skip to content

Commit

Permalink
refactor: ensure checks and utility functions reorg
Browse files Browse the repository at this point in the history
Co-authored-by: Igor Papandinas <[email protected]>
  • Loading branch information
prxgr4mm3r and ipapandinas authored Mar 18, 2024
1 parent 051bced commit 4efab90
Show file tree
Hide file tree
Showing 15 changed files with 290 additions and 297 deletions.
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

0 comments on commit 4efab90

Please sign in to comment.