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

Feature/init convert #136

Merged
merged 49 commits into from
May 17, 2023
Merged
Show file tree
Hide file tree
Changes from 41 commits
Commits
Show all changes
49 commits
Select commit Hold shift + click to select a range
0e26da7
cleanup
codespool Mar 24, 2023
0189647
remove timestamp from compile step
codespool Mar 27, 2023
37644c7
cleanup
codespool Mar 27, 2023
efe2601
remove timestamp from test report path
codespool Mar 27, 2023
aa5736d
init inherit BaseCommand
codespool Apr 3, 2023
69fafb2
add NO_CONFIG_COMMANDS list
codespool Apr 3, 2023
2a482c4
take a path for convert
codespool Apr 3, 2023
c36253b
add project dir check if empty
codespool Apr 3, 2023
9f9582b
introduce task queue, extract generate
codespool Apr 3, 2023
3931500
move test reports to test directory
codespool Apr 3, 2023
5a6ca70
simplify contract name gathering
codespool Apr 3, 2023
14dcbb3
detect contracts from workspace in cargo.toml
codespool Apr 13, 2023
b07136e
wip: parse workspace for contract list
codespool Apr 18, 2023
7c1e0f0
wip: add manual paths entry
codespool Apr 27, 2023
183b373
use fuzzypath instead of tree selector
codespool May 2, 2023
6442522
add test detection
codespool May 2, 2023
ea712e4
confirmed files to copy
codespool May 2, 2023
e58c56c
wip: copy selected files and dirs
codespool May 8, 2023
a3a64a0
replace TOML lib
codespool May 8, 2023
318f139
wip: copy toolchain files
codespool May 8, 2023
fbb90be
separate common and contract template processing
codespool May 8, 2023
ede5dd1
merge package.json
codespool May 8, 2023
72d73a1
v2.2.0-alpha.0
codespool May 8, 2023
1619f6a
clean up
codespool May 8, 2023
cae0d6d
use tests instead of test for directory name
codespool May 8, 2023
c9c3aaa
Merge branch 'master' into feature/init-convert
codespool May 8, 2023
4c1f5e5
fix: test path
codespool May 8, 2023
3bc146d
fix iteration bug
codespool May 9, 2023
32ff5e9
Merge branch 'master' into feature/init-convert
codespool May 9, 2023
d2f8a41
fix: typo?
codespool May 10, 2023
5ab683c
remove ask! conditionals
codespool May 10, 2023
ef2265d
cleanup and fix compile and typeGen
codespool May 11, 2023
74c4571
fix PR comment bug
codespool May 11, 2023
b151414
add contract class
codespool May 11, 2023
1afaff4
use contract class in typegen and deploy
codespool May 11, 2023
bc40aa5
use contract class in contract test
codespool May 11, 2023
897bf2e
add more exclusions to fuzzy search
codespool May 12, 2023
269eef9
remove resolutions from package.json template
codespool May 12, 2023
2497a2b
simplify test detection and prompt
codespool May 12, 2023
43437fc
Merge branch 'master' into feature/init-convert
codespool May 12, 2023
eec9c6c
v2.2.1-alpha.0
codespool May 15, 2023
ba4ed39
pr fix: update test template paths
codespool May 16, 2023
c8f928d
make getManualPaths recursive
codespool May 16, 2023
c7548a7
remove automatic workspace detection
codespool May 16, 2023
f04ce13
restore .github dir copy
codespool May 16, 2023
62bbcc6
move account init inside the run method
codespool May 16, 2023
8bd8a04
v2.2.2-alpha.0
codespool May 16, 2023
40ad8b5
PR fix: correct path in flipper test template
codespool May 17, 2023
8490bb3
use snake_case for generated contracts moduleName
codespool May 17, 2023
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
2 changes: 1 addition & 1 deletion lerna.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"$schema": "node_modules/lerna/schemas/lerna-schema.json",
"useWorkspaces": true,
"version": "2.1.2",
"version": "2.2.1-alpha.0",
"npmClient": "yarn"
}
17 changes: 9 additions & 8 deletions packages/cli/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ $ npm install -g @astar-network/swanky-cli
$ swanky COMMAND
running command...
$ swanky (--version|-V|-v)
@astar-network/swanky-cli/2.1.2 darwin-arm64 node-v18.10.0
@astar-network/swanky-cli/2.2.1-alpha.0 darwin-x64 node-v18.2.0
$ swanky --help [COMMAND]
USAGE
$ swanky COMMAND
Expand Down Expand Up @@ -114,7 +114,7 @@ DESCRIPTION
Check installed package versions and compatibility
```

_See code: [dist/commands/check/index.js](https://github.com/AstarNetwork/swanky-cli/blob/v2.1.2/dist/commands/check/index.js)_
_See code: [dist/commands/check/index.js](https://github.com/AstarNetwork/swanky-cli/blob/v2.2.1-alpha.0/dist/commands/check/index.js)_

## `swanky contract compile [CONTRACTNAME]`

Expand Down Expand Up @@ -160,7 +160,7 @@ DESCRIPTION

## `swanky contract explain CONTRACTNAME`

Explain contract messages based on thier metadata
Explain contract messages based on the contracts' metadata

```
USAGE
Expand All @@ -173,7 +173,7 @@ FLAGS
-v, --verbose Display more info in the result logs

DESCRIPTION
Explain contract messages based on thier metadata
Explain contract messages based on the contracts' metadata
```

## `swanky contract new CONTRACTNAME`
Expand Down Expand Up @@ -300,23 +300,24 @@ Generate a new smart contract environment

```
USAGE
$ swanky init PROJECTNAME [--swanky-node] [-t blank|erc20token|flipper|blank|flipper|psp22] [-l ask|ink]
[-v]
$ swanky init PROJECTNAME [-v] [--swanky-node] [-t blank|erc20token|flipper|blank|flipper|psp22] [-l
ask|ink] [-c <value>]

ARGUMENTS
PROJECTNAME directory name of new project

FLAGS
-c, --convert=<value> Converts an existing smart contract into a Swanky project
-l, --language=<option> <options: ask|ink>
-t, --template=<option> <options: blank|erc20token|flipper|blank|flipper|psp22>
-v, --verbose
-v, --verbose Display more info in the result logs
--swanky-node

DESCRIPTION
Generate a new smart contract environment
```

_See code: [dist/commands/init/index.js](https://github.com/AstarNetwork/swanky-cli/blob/v2.1.2/dist/commands/init/index.js)_
_See code: [dist/commands/init/index.js](https://github.com/AstarNetwork/swanky-cli/blob/v2.2.1-alpha.0/dist/commands/init/index.js)_

## `swanky node install`

Expand Down
15 changes: 10 additions & 5 deletions packages/cli/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@astar-network/swanky-cli",
"version": "2.1.2",
"version": "2.2.1-alpha.0",
"description": "Astar network WASM contract CLI tool",
"author": "Astar network",
"bin": {
Expand All @@ -17,39 +17,44 @@
"/oclif.manifest.json"
],
"dependencies": {
"@astar-network/swanky-core": "^2.1.2",
"@astar-network/swanky-templates": "^2.1.1",
"@astar-network/swanky-core": "^2.2.1-alpha.0",
"@astar-network/swanky-templates": "^2.2.1-alpha.0",
"@iarna/toml": "^2.2.5",
"@oclif/core": "2.5.0",
"@oclif/plugin-help": "5.2.7",
"@oclif/plugin-plugins": "2.3.2",
"@oclif/plugin-version": "1.2.1",
"@polkadot/util": "11.0.1",
"@polkadot/util-crypto": "11.0.1",
"@types/shelljs": "0.8.11",
"chalk": "4",
"change-case": "4.1.2",
"execa": "5.1.1",
"fs-extra": "10.1.0",
"globby": "11",
"inquirer": "8.2.5",
"inquirer-fuzzy-path": "^2.3.0",
"js-toml": "^0.1.1",
"listr2": "5.0.7",
"lodash": "^4.17.21",
"mocha": "10.2.0",
"mocha-suppress-logs": "0.3.1",
"mochawesome": "7.1.3",
"semver": "7.3.8",
"shelljs": "0.8.5",
"toml": "3.0.0",
"ts-mocha": "^10.0.0",
"typescript": "4.9.5"
},
"devDependencies": {
"@oclif/test": "2.3.9",
"@types/chai": "4",
"@types/fs-extra": "9.0.13",
"@types/iarna__toml": "^2.0.2",
"@types/inquirer": "8.2.5",
"@types/inquirer-fuzzy-path": "^2.3.6",
"@types/mocha": "9.0.0",
"@types/node": "18.11.9",
"@types/semver": "7.3.10",
"@types/shelljs": "0.8.11",
"@typescript-eslint/eslint-plugin": "5.35.1",
"@typescript-eslint/parser": "5.35.1",
"chai": "4",
Expand Down
4 changes: 2 additions & 2 deletions packages/cli/src/commands/check/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { Listr } from "listr2";
import { commandStdoutOrNull, ensureSwankyProject, SwankyConfig } from "@astar-network/swanky-core";
import fs = require("fs-extra");
import path = require("node:path");
import toml = require("toml");
import TOML from "@iarna/toml";
import semver = require("semver");

interface Ctx {
Expand Down Expand Up @@ -78,7 +78,7 @@ export default class Check extends Command {
encoding: "utf8",
});

const cargoToml = toml.parse(cargoTomlString);
const cargoToml = TOML.parse(cargoTomlString);

const inkDependencies = Object.entries(cargoToml.dependencies)
.filter((dependency) => dependency[0].includes("ink_"))
Expand Down
140 changes: 41 additions & 99 deletions packages/cli/src/commands/contract/compile.ts
Original file line number Diff line number Diff line change
@@ -1,49 +1,14 @@
import { Args, Command, Flags } from "@oclif/core";
import path = require("node:path");
import Files from "fs";
import fs = require("fs-extra");
import {
storeArtifacts,
ensureSwankyProject,
ContractData,
getSwankyConfig,
BuildData,
Spinner,
generateTypes,
} from "@astar-network/swanky-core";
import { ChildProcessWithoutNullStreams, spawn } from "node:child_process";
import { writeJSON, existsSync } from "fs-extra";

function getBuildCommandFor(
language: ContractData["language"],
contractPath: string,
release: boolean,
) : ChildProcessWithoutNullStreams {
if (language === "ink") {
const args = ["contract", "build", "--manifest-path", `${contractPath}/Cargo.toml`]
if (release) {
args.push("--release")
}
return spawn(
"cargo",
args
)
}
if (language === "ask") {
const args = ["asc", "--config", `${contractPath}/asconfig.json`, `${contractPath}/index.ts`];
if (release) {
args.push("-O");
args.push("--noAssert");
}
return spawn(
"npx",
args,
{ env: { ...process.env, ASK_CONFIG: `${contractPath}/askconfig.json` } }
);
}
throw new Error("Unsupported language!");
}

import { spawn } from "node:child_process";
import { pathExists } from "fs-extra";

export class CompileContract extends Command {
static description = "Compile the smart contract(s) in your contracts directory";
Expand All @@ -57,13 +22,14 @@ export class CompileContract extends Command {
release: Flags.boolean({
default: false,
char: "r",
description: "A production contract should always be build in `release` mode for building optimized wasm"
description:
"A production contract should always be build in `release` mode for building optimized wasm",
}),
all: Flags.boolean({
default: false,
char: "a",
description: "Set all to true to compile all contracts"
})
description: "Set all to true to compile all contracts",
}),
};

static args = {
Expand All @@ -79,99 +45,75 @@ export class CompileContract extends Command {
const { args, flags } = await this.parse(CompileContract);

if (args.contractName === undefined && !flags.all) {
this.error("No contracts were selected to compile")
this.error("No contracts were selected to compile");
}

await ensureSwankyProject();
const config = await getSwankyConfig();

const contractNames = [];
if (flags.all) {
for (const contractName of Object.keys(config.contracts)) {
console.log(`${contractName} contract is found`);
contractNames.push(contractName);
}
} else {
contractNames.push(args.contractName);
}

const contractNames = flags.all ? Object.keys(config.contracts) : [args.contractName];
const spinner = new Spinner();

for (const contractName of contractNames) {
const contractInfo = config.contracts[contractName];
if (!contractInfo) {
this.error(`Cannot find contract info for ${contractName} contract in swanky.config.json`);
}
const contractPath = path.resolve("contracts", contractName);
if (!existsSync(contractPath)) {
const contractPath = path.resolve("contracts", contractInfo.name);

if (!(await pathExists(contractPath))) {
this.error(`Contract folder not found at expected path`);
}

await spinner.runCommand(
const compilationResult = await spinner.runCommand(
async () => {
return new Promise<void>((resolve, reject) => {
const compile = getBuildCommandFor(contractInfo.language, contractPath, flags.release);
compile.stdout.on("data", () => spinner.ora.clear());
return new Promise<string>((resolve, reject) => {
const compileArgs = [
"contract",
"build",
"--manifest-path",
`${contractPath}/Cargo.toml`,
];
if (flags.release) {
compileArgs.push("--release");
}
const compile = spawn("cargo", compileArgs);
let outputBuffer = "";

compile.stdout.on("data", (data) => {
outputBuffer += data.toString();
spinner.ora.clear();
});
compile.stdout.pipe(process.stdout);

if (flags.verbose) {
compile.stderr.on("data", () => spinner.ora.clear());
compile.stderr.pipe(process.stdout);
}
compile.on("exit", (code) => {
if (code === 0) resolve();
else reject();
if (code === 0) {
const regex = /Your contract artifacts are ready\. You can find them in:\n(.*)/;
const match = outputBuffer.match(regex);
if (match) resolve(match[1]);
} else reject();
});
});
},
`Compiling ${contractName} contract`,
`${contractName} Contract compiled successfully`,
`${contractName} Contract compiled successfully`
);

// Depends on which language was used, the artifacts will be generated in different places at compile step.
let artifactsPath: string;
if (contractInfo.language === "ink") {
artifactsPath = path.resolve("target", "ink", `${contractName}`);
} else if (contractInfo.language === "ask") {
artifactsPath = path.resolve(contractPath, "build");
} else {
throw new Error("Unsupported language!");
}
const artifactsPath = compilationResult as string;

// Ask! build artifacts don't have `.contract` file which is just an combination of abi json and wasm blob
// `.contract` will have .source.wasm field whose value is wasm blob hex representation.
// Once Ask! support .contract file, this part will be removed.
if (contractInfo.language == "ask") {
// Unlike ink!, ask! names metadata file `metadata.json`. So, renaming it to contract name here needed for following tasks.
await fs.copyFile(
path.resolve(artifactsPath, "metadata.json"),
path.resolve(artifactsPath, `${contractName}.json`),
)
const contract = JSON.parse(Files.readFileSync(path.resolve(artifactsPath, `${contractName}.json`)).toString());
const wasmBuf = Files.readFileSync(path.resolve(artifactsPath, `${contractName}.wasm`));
const prefix = "0x"
contract.source.wasm = prefix + wasmBuf.toString("hex");
fs.writeFileSync(path.resolve(artifactsPath, `${contractName}.contract`), JSON.stringify(contract));
await fs.remove(path.resolve(artifactsPath, `${contractName}.wasm`));
}
await spinner.runCommand(async () => {
return storeArtifacts(artifactsPath, contractInfo.name, contractInfo.moduleName);
}, "Moving artifacts");

const typedContractDestPath = path.resolve("test", contractName, "typedContract");
await spinner.runCommand(
async () => await generateTypes(artifactsPath, contractName, typedContractDestPath),
async () => await generateTypes(contractInfo.name),
codespool marked this conversation as resolved.
Show resolved Hide resolved
`Generating ${contractName} contract ts types`,
`${contractName} contract's TS types Generated successfully`
);

const buildData = (await spinner.runCommand(async () => {
return storeArtifacts(artifactsPath, contractInfo.name);
}, "Moving artifacts")) as BuildData;

contractInfo.build = buildData;
}

await spinner.runCommand(async () => {
await writeJSON(path.resolve("swanky.config.json"), config, {
spaces: 2,
});
}, "Writing config");
}
}
Loading