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

Improved config feature #198

Merged
merged 36 commits into from
Feb 27, 2024
Merged
Show file tree
Hide file tree
Changes from 31 commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
d4a9163
Update SwankyConfig, make local and system configs
prxgr4mm3r Dec 29, 2023
cb80429
Clean up imports
prxgr4mm3r Dec 29, 2023
356ad63
Clean up imports
prxgr4mm3r Dec 29, 2023
9b264a7
Fix default account feature
prxgr4mm3r Jan 2, 2024
b70851d
Fixes
prxgr4mm3r Jan 24, 2024
355eb39
fix: Swanky config pre-populated in context to remove type assertions
ipapandinas Jan 25, 2024
2e3da70
fix: config update logic fixed for account create & default command
ipapandinas Jan 25, 2024
6007e31
fix: isLocalConfigCheck fixed
ipapandinas Jan 25, 2024
39bf8fa
fix: Allow some commands to be used without local config
ipapandinas Jan 25, 2024
5cff10e
fix: Wait for config store async functions
ipapandinas Jan 25, 2024
b8b947f
fix: isLocalConfigCheck fixed
ipapandinas Jan 26, 2024
e4fffc7
fix: Make config name dynamic
prxgr4mm3r Jan 26, 2024
fc0a000
fix: Make config name dynamic
prxgr4mm3r Jan 26, 2024
00ea4c5
Merge remote-tracking branch 'origin/feature/update-swanky-config' in…
prxgr4mm3r Jan 26, 2024
ede09f6
fix: Add alice and bob to accountsby default
prxgr4mm3r Jan 26, 2024
1c95829
fix: Display account alias in Errors
prxgr4mm3r Jan 26, 2024
7a42fd3
fix: Remove useless warning
prxgr4mm3r Jan 26, 2024
30000e8
fix: Change config merging
prxgr4mm3r Jan 26, 2024
b96ebfa
fix: Fix merging accounts created outside of project
prxgr4mm3r Jan 26, 2024
bb5f10b
fix: Fix mismatched versions displaying
prxgr4mm3r Jan 26, 2024
ebde7ad
fix: Remove useless debug output
prxgr4mm3r Jan 26, 2024
ba681bc
fix: Fix dev account check in local network
prxgr4mm3r Jan 26, 2024
15a0330
fix: Add check for node binary existence
prxgr4mm3r Jan 26, 2024
1ab38dd
fix: Correct account alias used for deploy and tx commands
ipapandinas Jan 30, 2024
9a25dd8
fix: Fix default command
prxgr4mm3r Jan 30, 2024
f9a604c
fix: Correct work when env SWANKY_CONFIG variable is set
prxgr4mm3r Jan 30, 2024
3a70313
feat: (WIP) Config builder created
ipapandinas Jan 30, 2024
64cda21
Merge remote-tracking branch 'origin/exploring-config-builder' into f…
prxgr4mm3r Jan 31, 2024
fe99bb1
fix: Correct use of new store config func
prxgr4mm3r Jan 31, 2024
93d41d6
fix: Use ConfigBuilder to change SwankyConfig
prxgr4mm3r Jan 31, 2024
4708ab4
fix: refactoring
ipapandinas Feb 1, 2024
78e0208
fix: Fix account storing
prxgr4mm3r Feb 2, 2024
01b7cf6
feat: addContractDeployment methode added to config builder
ipapandinas Feb 5, 2024
6a574a0
chore: chain configuration into a single builder expression
ipapandinas Feb 26, 2024
8ec01e2
Merge branch 'ink-devhub-1' into feature/update-swanky-config
ipapandinas Feb 26, 2024
563c96e
fix: config update for contract build verification
ipapandinas Feb 27, 2024
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
38 changes: 33 additions & 5 deletions src/commands/account/create.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,35 @@
import { Flags } from "@oclif/core";
import chalk from "chalk";
import { ChainAccount, encrypt } from "../../lib/index.js";
import { ChainAccount, encrypt, getSwankyConfig, isLocalConfigCheck } 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";
export class CreateAccount extends SwankyCommand<typeof CreateAccount> {
static description = "Create a new dev account in config";

static flags = {
generate: Flags.boolean({
global: 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<void> {
const { flags } = await this.parse(CreateAccount);

Expand All @@ -36,7 +50,7 @@ export class CreateAccount extends SwankyCommand<typeof CreateAccount> {
}

let tmpMnemonic = "";
if (flags.generate) {
if (flags.new) {
tmpMnemonic = ChainAccount.generate();
console.log(
`${
Expand Down Expand Up @@ -75,9 +89,23 @@ export class CreateAccount extends SwankyCommand<typeof CreateAccount> {
accountData.mnemonic = tmpMnemonic;
}

this.swankyConfig.accounts.push(accountData);
const configType = flags.global ? "global" : isLocalConfigCheck() ? "local" : "global";
const config = configType === "global" ? getSwankyConfig("global") : this.swankyConfig;

const configBuilder = new ConfigBuilder(config);
configBuilder.addAccount(accountData);

await this.storeConfig();
if (this.swankyConfig.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,
});
}

this.log(
`${chalk.greenBright("✔")} Account with alias ${chalk.yellowBright(
Expand Down
83 changes: 83 additions & 0 deletions src/commands/account/default.ts
ipapandinas marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
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<typeof DefaultAccount> {
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<void> {
const { args, flags } = await this.parse(DefaultAccount);

const configType = flags.global ? "global" : isLocalConfigCheck() ? "local" : "global";
const config = configType === "global" ? getSwankyConfig("global") : this.swankyConfig;
ipapandinas marked this conversation as resolved.
Show resolved Hide resolved

const accountAlias = args.accountAlias ?? (await this.promptForAccountAlias(config));
this.ensureAccountExists(config, accountAlias);

const configBuilder = new ConfigBuilder(config);
configBuilder.setDefaultAccount(accountAlias);

try {
await this.storeConfig(configBuilder.build(), configType);
ipapandinas marked this conversation as resolved.
Show resolved Hide resolved
} 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<string> {
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`);
}
}
31 changes: 28 additions & 3 deletions src/commands/account/list.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,36 @@ export class ListAccounts extends SwankyCommand<typeof ListAccounts> {
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<void> {
this.log(`${chalk.greenBright("✔")} Stored dev accounts:`);
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:`);

for (const account of this.swankyConfig.accounts) {
this.log(`\t${chalk.yellowBright("Alias: ")} ${account.alias}`);
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") : ""}`);
}
}
}
}
}
33 changes: 21 additions & 12 deletions src/commands/check/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Listr } from "listr2";
import { commandStdoutOrNull } from "../../lib/index.js";
import { commandStdoutOrNull, isLocalConfigCheck } from "../../lib/index.js";
import { SwankyConfig } from "../../types/index.js";
import { pathExistsSync, readJSON } from "fs-extra/esm";
import { pathExistsSync} from "fs-extra/esm";
import { readFileSync } from "fs";
import path from "node:path";
import TOML from "@iarna/toml";
Expand All @@ -19,14 +19,19 @@ interface Ctx {
};
contracts: Record<string, Record<string, string>>;
};
swankyConfig?: SwankyConfig;
swankyConfig: SwankyConfig;
mismatchedVersions?: Record<string, string>;
looseDefinitionDetected: boolean;
}

export default class Check extends SwankyCommand<typeof Check> {
static description = "Check installed package versions and compatibility";

constructor(argv: string[], baseConfig: any) {
super(argv, baseConfig);
(this.constructor as typeof SwankyCommand).ENSURE_SWANKY_CONFIG = false;
}

public async run(): Promise<void> {
const tasks = new Listr<Ctx>([
{
Expand Down Expand Up @@ -61,11 +66,10 @@ export default class Check extends SwankyCommand<typeof Check> {
},
{
title: "Read ink dependencies",
ipapandinas marked this conversation as resolved.
Show resolved Hide resolved
enabled: isLocalConfigCheck(),
skip: (ctx) => Object.keys(ctx.swankyConfig.contracts).length == 0,
task: async (ctx) => {
const swankyConfig = await readJSON("swanky.config.json");
ctx.swankyConfig = swankyConfig;

for (const contract in swankyConfig.contracts) {
for (const contract in ctx.swankyConfig.contracts) {
const tomlPath = path.resolve(`contracts/${contract}/Cargo.toml`);
const doesCargoTomlExist = pathExistsSync(tomlPath);
if (!doesCargoTomlExist) {
Expand All @@ -90,13 +94,15 @@ export default class Check extends SwankyCommand<typeof Check> {
},
{
title: "Verify ink version",
enabled: isLocalConfigCheck(),
skip: (ctx) => Object.keys(ctx.swankyConfig.contracts).length == 0,
task: async (ctx) => {
const supportedInk = ctx.swankyConfig?.node.supportedInk;
const supportedInk = ctx.swankyConfig.node.supportedInk;

const mismatched: Record<string, string> = {};
Object.entries(ctx.versions.contracts).forEach(([contract, inkPackages]) => {
Object.entries(inkPackages).forEach(([inkPackage, version]) => {
if (semver.gt(version, supportedInk!)) {
if (semver.gt(version, supportedInk)) {
mismatched[
`${contract}-${inkPackage}`
] = `Version of ${inkPackage} (${version}) in ${contract} is higher than supported ink version (${supportedInk})`;
Expand All @@ -114,12 +120,15 @@ export default class Check extends SwankyCommand<typeof Check> {
]);
const context = await tasks.run({
versions: { tools: {}, contracts: {} },
swankyConfig: this.swankyConfig,
looseDefinitionDetected: false,
});
console.log(context.versions);
Object.values(context.mismatchedVersions as any).forEach((mismatch) =>
console.error(`[ERROR] ${mismatch as string}`)
);
if(context.mismatchedVersions !== undefined) {
Object.values(context.mismatchedVersions).forEach((mismatch) =>
console.error(`[ERROR] ${mismatch}`)
);
}
if (context.looseDefinitionDetected) {
console.log(`\n[WARNING]Some of the ink dependencies do not have a fixed version.
This can lead to accidentally installing version higher than supported by the node.
Expand Down
4 changes: 2 additions & 2 deletions src/commands/contract/compile.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Args, Flags } from "@oclif/core";
import path from "node:path";
import { storeArtifacts, Spinner, generateTypes } from "../../lib/index.js";
import { storeArtifacts, Spinner, generateTypes, configName } from "../../lib/index.js";
import { spawn } from "node:child_process";
import { pathExists } from "fs-extra/esm";
import { SwankyCommand } from "../../lib/swankyCommand.js";
Expand Down Expand Up @@ -49,7 +49,7 @@ export class CompileContract extends SwankyCommand<typeof CompileContract> {
const contractInfo = this.swankyConfig.contracts[contractName];
if (!contractInfo) {
throw new ConfigError(
`Cannot find contract info for ${contractName} contract in swanky.config.json`
`Cannot find contract info for ${contractName} contract in "${configName()}"`
);
}
const contractPath = path.resolve("contracts", contractInfo.name);
Expand Down
38 changes: 26 additions & 12 deletions src/commands/contract/deploy.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
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 { resolveNetworkUrl, ChainApi, ChainAccount, decrypt, AbiType } from "../../lib/index.js";
import {
resolveNetworkUrl,
ChainApi,
ChainAccount,
decrypt,
AbiType,
ensureAccountIsSet,
configName,
} from "../../lib/index.js";
import { AccountData, Encrypted } from "../../types/index.js";
import inquirer from "inquirer";
import chalk from "chalk";
Expand All @@ -15,8 +21,7 @@ export class DeployContract extends SwankyCommand<typeof DeployContract> {

static flags = {
account: Flags.string({
required: true,
description: "Alias of account to be used",
description: "Account alias to deploy contract with",
}),
gas: Flags.integer({
char: "g",
Expand All @@ -32,6 +37,7 @@ export class DeployContract extends SwankyCommand<typeof DeployContract> {
}),
network: Flags.string({
char: "n",
default: "local",
description: "Network name to connect to",
}),
};
Expand All @@ -50,7 +56,7 @@ export class DeployContract extends SwankyCommand<typeof DeployContract> {
const contractRecord = this.swankyConfig.contracts[args.contractName];
if (!contractRecord) {
throw new ConfigError(
`Cannot find a contract named ${args.contractName} in swanky.config.json`
`Cannot find a contract named ${args.contractName} in "${configName()}"`
);
}

Expand All @@ -70,11 +76,21 @@ export class DeployContract extends SwankyCommand<typeof DeployContract> {
);
}

ensureAccountIsSet(flags.account, this.swankyConfig);

const accountAlias = flags.account ?? this.swankyConfig.defaultAccount;
ipapandinas marked this conversation as resolved.
Show resolved Hide resolved

const accountData = this.swankyConfig.accounts.find(
(account: AccountData) => account.alias === flags.account
(account: AccountData) => account.alias === accountAlias
);
if (!accountData) {
throw new ConfigError("Provided account alias not found in swanky.config.json");
throw new ConfigError(`Provided account alias ${chalk.yellowBright(accountAlias)} not found in "${configName()}"`);
}

if (accountData.isDev && flags.network !== "local") {
throw new ConfigError(
`Account ${accountAlias} is a DEV account and can only be used with local network`
);
}

const mnemonic = accountData.isDev
Expand Down Expand Up @@ -134,13 +150,11 @@ export class DeployContract extends SwankyCommand<typeof DeployContract> {
timestamp: Date.now(),
address: contractAddress,
networkUrl,
deployerAlias: flags.account,
deployerAlias: accountAlias!,
},
];

await writeJSON(path.resolve("swanky.config.json"), this.swankyConfig, {
spaces: 2,
});
await this.storeConfig(this.swankyConfig, 'local');
}, "Writing config");

this.log(`Contract deployed!`);
Expand Down
3 changes: 2 additions & 1 deletion src/commands/contract/explain.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,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";

export class ExplainContract extends SwankyCommand<typeof ExplainContract> {
static description = "Explain contract messages based on the contracts' metadata";
Expand All @@ -20,7 +21,7 @@ export class ExplainContract extends SwankyCommand<typeof ExplainContract> {
const contractRecord = this.swankyConfig.contracts[args.contractName];
if (!contractRecord) {
throw new ConfigError(
`Cannot find a contract named ${args.contractName} in swanky.config.json`
`Cannot find a contract named ${args.contractName} in "${configName()}"`
);
}

Expand Down
Loading
Loading