abc-blockchain 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/PUBLISHING.md +89 -0
- package/README.md +144 -0
- package/SECURITY.md +41 -0
- package/dist/branding.d.ts +7 -0
- package/dist/branding.js +14 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +31 -0
- package/dist/config.d.ts +22 -0
- package/dist/config.js +15 -0
- package/dist/create-project.d.ts +3 -0
- package/dist/create-project.js +55 -0
- package/dist/create-project.test.d.ts +1 -0
- package/dist/create-project.test.js +29 -0
- package/dist/logger.d.ts +7 -0
- package/dist/logger.js +15 -0
- package/dist/package-manager.d.ts +3 -0
- package/dist/package-manager.js +14 -0
- package/dist/template.d.ts +3 -0
- package/dist/template.js +30 -0
- package/package.json +72 -0
- package/templates/hardhat-erc4337/.env.example +7 -0
- package/templates/hardhat-erc4337/.eslintrc.cjs +14 -0
- package/templates/hardhat-erc4337/.github/workflows/ci.yml +36 -0
- package/templates/hardhat-erc4337/.github/workflows/release.yml +26 -0
- package/templates/hardhat-erc4337/.husky/pre-commit +1 -0
- package/templates/hardhat-erc4337/.prettierrc.json +7 -0
- package/templates/hardhat-erc4337/README.md.tmpl +98 -0
- package/templates/hardhat-erc4337/contracts/AccountFactory.sol +45 -0
- package/templates/hardhat-erc4337/contracts/EntryPoint.sol +69 -0
- package/templates/hardhat-erc4337/contracts/SmartAccount.sol +93 -0
- package/templates/hardhat-erc4337/contracts/Token.sol +15 -0
- package/templates/hardhat-erc4337/contracts/interfaces/IEntryPoint.sol +24 -0
- package/templates/hardhat-erc4337/contracts/interfaces/IPaymasterHook.sol +12 -0
- package/templates/hardhat-erc4337/deployments/.gitkeep +1 -0
- package/templates/hardhat-erc4337/hardhat.config.ts +41 -0
- package/templates/hardhat-erc4337/ignition/modules/AccountAbstraction.ts +14 -0
- package/templates/hardhat-erc4337/package.json.tmpl +62 -0
- package/templates/hardhat-erc4337/scripts/createAccount.ts +33 -0
- package/templates/hardhat-erc4337/scripts/deploy.ts +50 -0
- package/templates/hardhat-erc4337/scripts/lib/bundler.ts +17 -0
- package/templates/hardhat-erc4337/scripts/lib/env.ts +18 -0
- package/templates/hardhat-erc4337/scripts/lib/logger.ts +8 -0
- package/templates/hardhat-erc4337/slither.config.json +4 -0
- package/templates/hardhat-erc4337/tasks/accounts.ts +17 -0
- package/templates/hardhat-erc4337/test/SmartAccount.ts +32 -0
- package/templates/hardhat-erc4337/tsconfig.json +15 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Kimberley Bezuidenhout
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/PUBLISHING.md
ADDED
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
# Publishing ABC Blockchain to npm
|
|
2
|
+
|
|
3
|
+
Creator: Kimberley Bezuidenhout
|
|
4
|
+
Framework Signature: kimmicorn~glitch
|
|
5
|
+
|
|
6
|
+
## Prerequisites
|
|
7
|
+
|
|
8
|
+
- Node.js 20 or 22
|
|
9
|
+
- npm account with publish rights for `abc-blockchain`
|
|
10
|
+
- GitHub repository with Actions enabled
|
|
11
|
+
- npm automation token stored as `NPM_TOKEN`
|
|
12
|
+
|
|
13
|
+
## Local Release Checks
|
|
14
|
+
|
|
15
|
+
Run these before publishing:
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
npm ci
|
|
19
|
+
npm run ci
|
|
20
|
+
npm pack --dry-run
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
Confirm the dry-run package includes:
|
|
24
|
+
|
|
25
|
+
- `dist/`
|
|
26
|
+
- `templates/`
|
|
27
|
+
- `README.md`
|
|
28
|
+
- `LICENSE`
|
|
29
|
+
- no `.env`
|
|
30
|
+
- no `node_modules`
|
|
31
|
+
- no generated sample projects
|
|
32
|
+
|
|
33
|
+
## First-Time npm Setup
|
|
34
|
+
|
|
35
|
+
1. Create or log in to an npm account.
|
|
36
|
+
2. Enable two-factor authentication on the account.
|
|
37
|
+
3. Create an automation token at npm.
|
|
38
|
+
4. In GitHub, open repository settings.
|
|
39
|
+
5. Add `NPM_TOKEN` under `Settings > Secrets and variables > Actions`.
|
|
40
|
+
6. Create an environment named `npm-production`.
|
|
41
|
+
7. Add required reviewers to the `npm-production` environment.
|
|
42
|
+
|
|
43
|
+
## Manual Publish from GitHub Actions
|
|
44
|
+
|
|
45
|
+
1. Open `Actions`.
|
|
46
|
+
2. Select `Publish to npm`.
|
|
47
|
+
3. Click `Run workflow`.
|
|
48
|
+
4. Enter the version, for example `0.1.1`.
|
|
49
|
+
5. Keep `dry_run` enabled for the first run.
|
|
50
|
+
6. Review the workflow logs and package contents.
|
|
51
|
+
7. Run the workflow again with `dry_run` disabled.
|
|
52
|
+
|
|
53
|
+
The workflow runs CI, updates the package version, verifies package contents, publishes with npm provenance, commits the version bump, and creates a `vX.Y.Z` git tag.
|
|
54
|
+
|
|
55
|
+
## Manual Publish from Local Machine
|
|
56
|
+
|
|
57
|
+
Use this only if GitHub Actions is unavailable:
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
npm ci
|
|
61
|
+
npm run ci
|
|
62
|
+
npm version 0.1.1
|
|
63
|
+
npm publish --provenance --access public --tag latest
|
|
64
|
+
git push origin main --follow-tags
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
## Dist Tags
|
|
68
|
+
|
|
69
|
+
- `latest`: stable releases
|
|
70
|
+
- `next`: release candidates
|
|
71
|
+
- `beta`: beta releases
|
|
72
|
+
- `alpha`: early internal validation
|
|
73
|
+
|
|
74
|
+
Install examples:
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
npm install -g abc-blockchain@latest
|
|
78
|
+
npx abc-blockchain init my-project
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
## Production Release Checklist
|
|
82
|
+
|
|
83
|
+
- CI is green on `main`.
|
|
84
|
+
- `npm audit --audit-level=moderate` passes for the CLI package.
|
|
85
|
+
- Generated template compiles and tests with a fresh install.
|
|
86
|
+
- README, SECURITY, and PUBLISHING docs match the release.
|
|
87
|
+
- Package contents were reviewed through `npm pack --dry-run`.
|
|
88
|
+
- GitHub environment approval is enabled for `npm-production`.
|
|
89
|
+
- `NPM_TOKEN` is an npm automation token, not a personal password.
|
package/README.md
ADDED
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
# ABC Blockchain
|
|
2
|
+
|
|
3
|
+
Enterprise-grade npm bootstrap framework for ERC-4337 Hardhat development environments.
|
|
4
|
+
|
|
5
|
+
Creator: Kimberley Bezuidenhout
|
|
6
|
+
Framework Signature: kimmicorn~glitch
|
|
7
|
+
|
|
8
|
+
## Usage
|
|
9
|
+
|
|
10
|
+
```bash
|
|
11
|
+
npx abc-blockchain init my-project
|
|
12
|
+
cd my-project
|
|
13
|
+
npm test
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
The generated project includes Solidity contracts, Hardhat, TypeScript, Ethers v6, OpenZeppelin, dotenv validation, CI, release workflow, linting, formatting, security scanning hooks, deployment scripts, tests, and ERC-4337 integration points.
|
|
17
|
+
|
|
18
|
+
## CLI
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
abc-blockchain init <project-name> [--no-install] [--package-manager npm|pnpm|yarn]
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## Generated File Tree
|
|
25
|
+
|
|
26
|
+
```text
|
|
27
|
+
my-project/
|
|
28
|
+
├── contracts/
|
|
29
|
+
│ ├── interfaces/
|
|
30
|
+
│ │ ├── IEntryPoint.sol
|
|
31
|
+
│ │ └── IPaymasterHook.sol
|
|
32
|
+
│ ├── SmartAccount.sol
|
|
33
|
+
│ ├── AccountFactory.sol
|
|
34
|
+
│ ├── EntryPoint.sol
|
|
35
|
+
│ └── Token.sol
|
|
36
|
+
├── scripts/
|
|
37
|
+
│ ├── lib/
|
|
38
|
+
│ │ ├── bundler.ts
|
|
39
|
+
│ │ ├── env.ts
|
|
40
|
+
│ │ └── logger.ts
|
|
41
|
+
│ ├── createAccount.ts
|
|
42
|
+
│ └── deploy.ts
|
|
43
|
+
├── deployments/
|
|
44
|
+
├── ignition/
|
|
45
|
+
│ └── modules/
|
|
46
|
+
│ └── AccountAbstraction.ts
|
|
47
|
+
├── tasks/
|
|
48
|
+
│ └── accounts.ts
|
|
49
|
+
├── test/
|
|
50
|
+
│ └── SmartAccount.ts
|
|
51
|
+
├── .github/workflows/
|
|
52
|
+
│ ├── ci.yml
|
|
53
|
+
│ └── release.yml
|
|
54
|
+
├── hardhat.config.ts
|
|
55
|
+
├── tsconfig.json
|
|
56
|
+
├── .env.example
|
|
57
|
+
├── README.md
|
|
58
|
+
└── package.json
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## Architecture
|
|
62
|
+
|
|
63
|
+
- CLI package copies a versioned Hardhat template and renders project metadata.
|
|
64
|
+
- Generated projects keep contracts, scripts, tasks, tests, deployments, and CI concerns separated.
|
|
65
|
+
- Environment variables are parsed through Zod so missing or malformed configuration fails early.
|
|
66
|
+
- Deployment scripts emit structured JSON logs and deployment manifests.
|
|
67
|
+
- No telemetry, hidden network calls, covert tracking, or obfuscated code is included.
|
|
68
|
+
|
|
69
|
+
## Implementation Roadmap
|
|
70
|
+
|
|
71
|
+
1. Stabilize v0.1 template with EntryPoint integration, smart account factory, deterministic deployments, and tests.
|
|
72
|
+
2. Add selectable templates for minimal, audited, upgradeable, and paymaster-enabled project profiles.
|
|
73
|
+
3. Add real bundler and paymaster provider adapters for common ERC-4337 infrastructure vendors.
|
|
74
|
+
4. Add Foundry optional profile, Slither CI container job, and contract size reporting.
|
|
75
|
+
5. Add template snapshot tests and generated-project compile tests in CI.
|
|
76
|
+
6. Publish v1.0 after external security review and compatibility checks across Node LTS versions.
|
|
77
|
+
|
|
78
|
+
## Release Plan
|
|
79
|
+
|
|
80
|
+
- Use semantic versioning.
|
|
81
|
+
- `0.x`: rapid template iteration, breaking changes allowed with changelog entries.
|
|
82
|
+
- `1.0`: stable CLI flags, stable generated folder contracts, documented migration guide.
|
|
83
|
+
- Patch releases: bug fixes, dependency security bumps, documentation corrections.
|
|
84
|
+
- Minor releases: new template options, new provider adapters, additional CI integrations.
|
|
85
|
+
- Major releases: Hardhat or ERC-4337 interface upgrades that require user migration.
|
|
86
|
+
|
|
87
|
+
## NPM Publishing Workflow
|
|
88
|
+
|
|
89
|
+
This repository ships a production-oriented manual publish workflow at `.github/workflows/publish-npm.yml`.
|
|
90
|
+
|
|
91
|
+
Local checks:
|
|
92
|
+
|
|
93
|
+
```bash
|
|
94
|
+
npm ci
|
|
95
|
+
npm run ci
|
|
96
|
+
npm pack --dry-run
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
GitHub setup:
|
|
100
|
+
|
|
101
|
+
1. Create an npm automation token.
|
|
102
|
+
2. Store it in GitHub Actions secrets as `NPM_TOKEN`.
|
|
103
|
+
3. Create a GitHub environment named `npm-production`.
|
|
104
|
+
4. Add required reviewers to the environment.
|
|
105
|
+
5. Run the `Publish to npm` workflow with `dry_run` enabled first.
|
|
106
|
+
6. Re-run the workflow with `dry_run` disabled when the package contents are correct.
|
|
107
|
+
|
|
108
|
+
Manual fallback:
|
|
109
|
+
|
|
110
|
+
```bash
|
|
111
|
+
npm ci
|
|
112
|
+
npm run ci
|
|
113
|
+
npm version 0.1.1
|
|
114
|
+
npm publish --provenance --access public
|
|
115
|
+
git push origin main --follow-tags
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
See `PUBLISHING.md` for the full release checklist.
|
|
119
|
+
|
|
120
|
+
## Repository Structure
|
|
121
|
+
|
|
122
|
+
```text
|
|
123
|
+
abc-blockchain/
|
|
124
|
+
├── src/
|
|
125
|
+
│ ├── branding.ts
|
|
126
|
+
│ ├── cli.ts
|
|
127
|
+
│ ├── config.ts
|
|
128
|
+
│ ├── create-project.ts
|
|
129
|
+
│ ├── logger.ts
|
|
130
|
+
│ ├── package-manager.ts
|
|
131
|
+
│ └── template.ts
|
|
132
|
+
├── templates/
|
|
133
|
+
│ └── hardhat-erc4337/
|
|
134
|
+
├── .github/workflows/
|
|
135
|
+
├── PUBLISHING.md
|
|
136
|
+
├── SECURITY.md
|
|
137
|
+
├── package.json
|
|
138
|
+
├── tsconfig.json
|
|
139
|
+
└── README.md
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
## Security Position
|
|
143
|
+
|
|
144
|
+
ABC Blockchain intentionally avoids hardcoded secrets, hidden backdoors, malicious telemetry, covert tracking, and opaque logic. Generated projects include environment validation, dependency audit scripts, CodeQL scanning, Slither-ready configuration, and audit-friendly folder boundaries.
|
package/SECURITY.md
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# Security Policy
|
|
2
|
+
|
|
3
|
+
## Supported Versions
|
|
4
|
+
|
|
5
|
+
ABC Blockchain is pre-1.0. Security fixes are released on the latest minor line.
|
|
6
|
+
|
|
7
|
+
## Reporting a Vulnerability
|
|
8
|
+
|
|
9
|
+
Report vulnerabilities privately to the repository maintainer. Do not open public issues for suspected exploitable behavior.
|
|
10
|
+
|
|
11
|
+
Include:
|
|
12
|
+
|
|
13
|
+
- Affected version
|
|
14
|
+
- Reproduction steps
|
|
15
|
+
- Impact assessment
|
|
16
|
+
- Suggested fix, if known
|
|
17
|
+
|
|
18
|
+
## Security Guarantees
|
|
19
|
+
|
|
20
|
+
ABC Blockchain does not include hidden telemetry, covert tracking, backdoors, or obfuscated logic.
|
|
21
|
+
|
|
22
|
+
Generated projects are designed to avoid hardcoded secrets and include:
|
|
23
|
+
|
|
24
|
+
- `.env.example` with no real credentials
|
|
25
|
+
- Zod environment validation
|
|
26
|
+
- GitHub Actions CI
|
|
27
|
+
- npm audit gate
|
|
28
|
+
- CodeQL analysis
|
|
29
|
+
- Slither-ready Solidity layout
|
|
30
|
+
- Explicit creator attribution
|
|
31
|
+
|
|
32
|
+
## Required Production Review
|
|
33
|
+
|
|
34
|
+
Before deploying generated contracts to production:
|
|
35
|
+
|
|
36
|
+
- Replace the development `EntryPoint.sol` with the canonical audited ERC-4337 EntryPoint for the target network.
|
|
37
|
+
- Run Slither and review all findings.
|
|
38
|
+
- Run gas reports for account validation and execution paths.
|
|
39
|
+
- Review UUPS upgrade ownership and transfer it to a multisig or governance process.
|
|
40
|
+
- Audit paymaster and bundler trust assumptions.
|
|
41
|
+
- Pin dependency versions for audited releases.
|
package/dist/branding.js
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export const BRAND = {
|
|
2
|
+
packageName: "abc-blockchain",
|
|
3
|
+
frameworkName: "ABC Blockchain",
|
|
4
|
+
creator: "Kimberley Bezuidenhout",
|
|
5
|
+
signature: "kimmicorn~glitch"
|
|
6
|
+
};
|
|
7
|
+
export function banner() {
|
|
8
|
+
return [
|
|
9
|
+
"ABC Blockchain",
|
|
10
|
+
`Creator: ${BRAND.creator}`,
|
|
11
|
+
`Framework Signature: ${BRAND.signature}`,
|
|
12
|
+
"Enterprise ERC-4337 Hardhat bootstrap"
|
|
13
|
+
].join("\n");
|
|
14
|
+
}
|
package/dist/cli.d.ts
ADDED
package/dist/cli.js
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { Command } from "commander";
|
|
3
|
+
import { banner, BRAND } from "./branding.js";
|
|
4
|
+
import { createProject } from "./create-project.js";
|
|
5
|
+
import { logger } from "./logger.js";
|
|
6
|
+
const program = new Command();
|
|
7
|
+
program
|
|
8
|
+
.name(BRAND.packageName)
|
|
9
|
+
.description("Generate enterprise-grade ERC-4337 Hardhat development environments.")
|
|
10
|
+
.version("0.1.0");
|
|
11
|
+
program
|
|
12
|
+
.command("init")
|
|
13
|
+
.argument("<project-name>", "Project directory and npm package name")
|
|
14
|
+
.option("--no-install", "Skip dependency installation")
|
|
15
|
+
.option("--package-manager <manager>", "npm, pnpm, or yarn", "npm")
|
|
16
|
+
.action(async (projectName, options) => {
|
|
17
|
+
console.log(banner());
|
|
18
|
+
try {
|
|
19
|
+
await createProject({
|
|
20
|
+
projectName,
|
|
21
|
+
cwd: process.cwd(),
|
|
22
|
+
install: options.install,
|
|
23
|
+
packageManager: options.packageManager
|
|
24
|
+
}, logger);
|
|
25
|
+
}
|
|
26
|
+
catch (error) {
|
|
27
|
+
logger.error(error instanceof Error ? error.message : String(error));
|
|
28
|
+
process.exitCode = 1;
|
|
29
|
+
}
|
|
30
|
+
});
|
|
31
|
+
await program.parseAsync(process.argv);
|
package/dist/config.d.ts
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export declare const InitOptionsSchema: z.ZodObject<{
|
|
3
|
+
projectName: z.ZodString;
|
|
4
|
+
cwd: z.ZodString;
|
|
5
|
+
install: z.ZodDefault<z.ZodBoolean>;
|
|
6
|
+
packageManager: z.ZodDefault<z.ZodEnum<["npm", "pnpm", "yarn"]>>;
|
|
7
|
+
}, "strip", z.ZodTypeAny, {
|
|
8
|
+
projectName: string;
|
|
9
|
+
cwd: string;
|
|
10
|
+
install: boolean;
|
|
11
|
+
packageManager: "npm" | "pnpm" | "yarn";
|
|
12
|
+
}, {
|
|
13
|
+
projectName: string;
|
|
14
|
+
cwd: string;
|
|
15
|
+
install?: boolean | undefined;
|
|
16
|
+
packageManager?: "npm" | "pnpm" | "yarn" | undefined;
|
|
17
|
+
}>;
|
|
18
|
+
export type InitOptions = z.infer<typeof InitOptionsSchema>;
|
|
19
|
+
export type ResolvedInitConfig = InitOptions & {
|
|
20
|
+
targetDirectory: string;
|
|
21
|
+
};
|
|
22
|
+
export declare function resolveInitConfig(input: InitOptions): ResolvedInitConfig;
|
package/dist/config.js
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
export const InitOptionsSchema = z.object({
|
|
4
|
+
projectName: z.string().min(1),
|
|
5
|
+
cwd: z.string().min(1),
|
|
6
|
+
install: z.boolean().default(true),
|
|
7
|
+
packageManager: z.enum(["npm", "pnpm", "yarn"]).default("npm")
|
|
8
|
+
});
|
|
9
|
+
export function resolveInitConfig(input) {
|
|
10
|
+
const options = InitOptionsSchema.parse(input);
|
|
11
|
+
return {
|
|
12
|
+
...options,
|
|
13
|
+
targetDirectory: path.resolve(options.cwd, options.projectName)
|
|
14
|
+
};
|
|
15
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { spawn } from "node:child_process";
|
|
2
|
+
import fs from "fs-extra";
|
|
3
|
+
import validatePackageName from "validate-npm-package-name";
|
|
4
|
+
import { BRAND } from "./branding.js";
|
|
5
|
+
import { resolveInitConfig } from "./config.js";
|
|
6
|
+
import { displayRunCommand, installCommand } from "./package-manager.js";
|
|
7
|
+
import { copyTemplate } from "./template.js";
|
|
8
|
+
export async function createProject(input, log) {
|
|
9
|
+
const config = resolveInitConfig(input);
|
|
10
|
+
const validation = validatePackageName(config.projectName);
|
|
11
|
+
if (!validation.validForNewPackages) {
|
|
12
|
+
throw new Error([...(validation.errors ?? []), ...(validation.warnings ?? [])].join("\n") ||
|
|
13
|
+
"Project name is not a valid npm package name.");
|
|
14
|
+
}
|
|
15
|
+
if (await fs.pathExists(config.targetDirectory)) {
|
|
16
|
+
const existing = await fs.readdir(config.targetDirectory);
|
|
17
|
+
if (existing.length > 0) {
|
|
18
|
+
throw new Error(`Target directory is not empty: ${config.targetDirectory}`);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
await fs.ensureDir(config.targetDirectory);
|
|
22
|
+
await copyTemplate(config.targetDirectory, {
|
|
23
|
+
projectName: config.projectName,
|
|
24
|
+
creator: BRAND.creator,
|
|
25
|
+
signature: BRAND.signature
|
|
26
|
+
});
|
|
27
|
+
log.success(`Generated ${config.projectName} at ${config.targetDirectory}`);
|
|
28
|
+
if (config.install) {
|
|
29
|
+
const [command, ...args] = installCommand(config.packageManager);
|
|
30
|
+
log.info(`Installing dependencies with ${config.packageManager}...`);
|
|
31
|
+
await run(command, args, config.targetDirectory);
|
|
32
|
+
}
|
|
33
|
+
else {
|
|
34
|
+
log.warn("Skipped dependency installation.");
|
|
35
|
+
}
|
|
36
|
+
log.success("ABC Blockchain project ready.");
|
|
37
|
+
log.info(`Next: cd ${config.projectName}`);
|
|
38
|
+
log.info(`Test: ${displayRunCommand(config.packageManager, "test")}`);
|
|
39
|
+
}
|
|
40
|
+
function run(command, args, cwd) {
|
|
41
|
+
return new Promise((resolve, reject) => {
|
|
42
|
+
const child = spawn(command, args, {
|
|
43
|
+
cwd,
|
|
44
|
+
stdio: "inherit",
|
|
45
|
+
shell: process.platform === "win32"
|
|
46
|
+
});
|
|
47
|
+
child.on("error", reject);
|
|
48
|
+
child.on("close", (code) => {
|
|
49
|
+
if (code === 0)
|
|
50
|
+
resolve();
|
|
51
|
+
else
|
|
52
|
+
reject(new Error(`${command} ${args.join(" ")} exited with code ${code}`));
|
|
53
|
+
});
|
|
54
|
+
});
|
|
55
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import fs from "fs-extra";
|
|
2
|
+
import assert from "node:assert/strict";
|
|
3
|
+
import os from "node:os";
|
|
4
|
+
import path from "node:path";
|
|
5
|
+
import { describe, it } from "node:test";
|
|
6
|
+
import { createProject } from "./create-project.js";
|
|
7
|
+
const silentLogger = {
|
|
8
|
+
info() { },
|
|
9
|
+
success() { },
|
|
10
|
+
warn() { },
|
|
11
|
+
error() { }
|
|
12
|
+
};
|
|
13
|
+
void describe("createProject", () => {
|
|
14
|
+
void it("generates a complete Hardhat ERC-4337 project", async () => {
|
|
15
|
+
const cwd = await fs.mkdtemp(path.join(os.tmpdir(), "abc-blockchain-"));
|
|
16
|
+
await createProject({
|
|
17
|
+
projectName: "sample-aa",
|
|
18
|
+
cwd,
|
|
19
|
+
install: false,
|
|
20
|
+
packageManager: "npm"
|
|
21
|
+
}, silentLogger);
|
|
22
|
+
const projectRoot = path.join(cwd, "sample-aa");
|
|
23
|
+
assert.equal(await fs.pathExists(path.join(projectRoot, "contracts", "SmartAccount.sol")), true);
|
|
24
|
+
const generatedPackage = await fs.readJson(path.join(projectRoot, "package.json"));
|
|
25
|
+
assert.equal(generatedPackage.name, "sample-aa");
|
|
26
|
+
assert.equal(generatedPackage.abcBlockchain.creator, "Kimberley Bezuidenhout");
|
|
27
|
+
assert.equal(generatedPackage.abcBlockchain.signature, "kimmicorn~glitch");
|
|
28
|
+
});
|
|
29
|
+
});
|
package/dist/logger.d.ts
ADDED
package/dist/logger.js
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import chalk from "chalk";
|
|
2
|
+
export const logger = {
|
|
3
|
+
info(message) {
|
|
4
|
+
console.log(chalk.cyan("info"), message);
|
|
5
|
+
},
|
|
6
|
+
success(message) {
|
|
7
|
+
console.log(chalk.green("done"), message);
|
|
8
|
+
},
|
|
9
|
+
warn(message) {
|
|
10
|
+
console.warn(chalk.yellow("warn"), message);
|
|
11
|
+
},
|
|
12
|
+
error(message) {
|
|
13
|
+
console.error(chalk.red("error"), message);
|
|
14
|
+
}
|
|
15
|
+
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export function installCommand(packageManager) {
|
|
2
|
+
if (packageManager === "yarn")
|
|
3
|
+
return ["yarn"];
|
|
4
|
+
if (packageManager === "pnpm")
|
|
5
|
+
return ["pnpm", "install"];
|
|
6
|
+
return ["npm", "install"];
|
|
7
|
+
}
|
|
8
|
+
export function displayRunCommand(packageManager, script) {
|
|
9
|
+
if (packageManager === "yarn")
|
|
10
|
+
return `yarn ${script}`;
|
|
11
|
+
if (packageManager === "pnpm")
|
|
12
|
+
return `pnpm ${script}`;
|
|
13
|
+
return `npm run ${script}`;
|
|
14
|
+
}
|
package/dist/template.js
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import fs from "fs-extra";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { fileURLToPath } from "node:url";
|
|
4
|
+
const dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
5
|
+
export function templateRoot() {
|
|
6
|
+
return path.resolve(dirname, "../templates/hardhat-erc4337");
|
|
7
|
+
}
|
|
8
|
+
export async function copyTemplate(targetDirectory, variables) {
|
|
9
|
+
await fs.copy(templateRoot(), targetDirectory, {
|
|
10
|
+
filter: (source) => !source.endsWith(".DS_Store")
|
|
11
|
+
});
|
|
12
|
+
await renderTemplates(targetDirectory, variables);
|
|
13
|
+
}
|
|
14
|
+
async function renderTemplates(directory, variables) {
|
|
15
|
+
const entries = await fs.readdir(directory, { withFileTypes: true });
|
|
16
|
+
await Promise.all(entries.map(async (entry) => {
|
|
17
|
+
const absolutePath = path.join(directory, entry.name);
|
|
18
|
+
if (entry.isDirectory()) {
|
|
19
|
+
await renderTemplates(absolutePath, variables);
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
if (!entry.name.endsWith(".tmpl"))
|
|
23
|
+
return;
|
|
24
|
+
const outputPath = absolutePath.replace(/\.tmpl$/, "");
|
|
25
|
+
const source = await fs.readFile(absolutePath, "utf8");
|
|
26
|
+
const rendered = Object.entries(variables).reduce((next, [key, value]) => next.replaceAll(`{{${key}}}`, value), source);
|
|
27
|
+
await fs.writeFile(outputPath, rendered, "utf8");
|
|
28
|
+
await fs.remove(absolutePath);
|
|
29
|
+
}));
|
|
30
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "abc-blockchain",
|
|
3
|
+
"version": "0.1.1",
|
|
4
|
+
"description": "Enterprise-grade ERC-4337 Hardhat bootstrap framework.",
|
|
5
|
+
"author": "Kimberley Bezuidenhout",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"type": "module",
|
|
8
|
+
"bin": {
|
|
9
|
+
"abc-blockchain": "./dist/cli.js"
|
|
10
|
+
},
|
|
11
|
+
"files": [
|
|
12
|
+
"dist",
|
|
13
|
+
"templates",
|
|
14
|
+
"README.md",
|
|
15
|
+
"PUBLISHING.md",
|
|
16
|
+
"SECURITY.md",
|
|
17
|
+
"LICENSE"
|
|
18
|
+
],
|
|
19
|
+
"scripts": {
|
|
20
|
+
"build": "tsc -p tsconfig.json",
|
|
21
|
+
"ci": "npm run format:check && npm run lint && npm test && npm audit --audit-level=moderate && npm run pack:check",
|
|
22
|
+
"dev": "tsx src/cli.ts",
|
|
23
|
+
"lint": "eslint \"src/**/*.ts\"",
|
|
24
|
+
"format": "prettier --write .",
|
|
25
|
+
"format:check": "prettier --check .",
|
|
26
|
+
"test": "npm run build && node --test dist/create-project.test.js",
|
|
27
|
+
"pack:check": "npm pack --dry-run",
|
|
28
|
+
"prepack": "npm run build",
|
|
29
|
+
"prepare": "husky",
|
|
30
|
+
"release": "npm publish --provenance --access public"
|
|
31
|
+
},
|
|
32
|
+
"keywords": [
|
|
33
|
+
"erc-4337",
|
|
34
|
+
"hardhat",
|
|
35
|
+
"account-abstraction",
|
|
36
|
+
"ethereum",
|
|
37
|
+
"smart-contracts",
|
|
38
|
+
"bootstrap"
|
|
39
|
+
],
|
|
40
|
+
"abcBlockchain": {
|
|
41
|
+
"creator": "Kimberley Bezuidenhout",
|
|
42
|
+
"signature": "kimmicorn~glitch",
|
|
43
|
+
"telemetry": false
|
|
44
|
+
},
|
|
45
|
+
"dependencies": {
|
|
46
|
+
"chalk": "^5.3.0",
|
|
47
|
+
"commander": "^12.1.0",
|
|
48
|
+
"fs-extra": "^11.2.0",
|
|
49
|
+
"ora": "^8.0.1",
|
|
50
|
+
"validate-npm-package-name": "^5.0.1",
|
|
51
|
+
"zod": "^3.23.8"
|
|
52
|
+
},
|
|
53
|
+
"devDependencies": {
|
|
54
|
+
"@types/fs-extra": "^11.0.4",
|
|
55
|
+
"@types/node": "^20.14.10",
|
|
56
|
+
"@types/validate-npm-package-name": "^4.0.2",
|
|
57
|
+
"@typescript-eslint/eslint-plugin": "^7.16.0",
|
|
58
|
+
"@typescript-eslint/parser": "^7.16.0",
|
|
59
|
+
"eslint": "^8.57.0",
|
|
60
|
+
"husky": "^9.1.1",
|
|
61
|
+
"prettier": "^3.3.3",
|
|
62
|
+
"prettier-plugin-solidity": "^1.3.1",
|
|
63
|
+
"tsx": "^4.16.2",
|
|
64
|
+
"typescript": "^5.5.3"
|
|
65
|
+
},
|
|
66
|
+
"publishConfig": {
|
|
67
|
+
"access": "public"
|
|
68
|
+
},
|
|
69
|
+
"engines": {
|
|
70
|
+
"node": ">=20.0.0"
|
|
71
|
+
}
|
|
72
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
module.exports = {
|
|
2
|
+
root: true,
|
|
3
|
+
parser: "@typescript-eslint/parser",
|
|
4
|
+
plugins: ["@typescript-eslint"],
|
|
5
|
+
extends: ["eslint:recommended", "plugin:@typescript-eslint/recommended", "prettier"],
|
|
6
|
+
env: {
|
|
7
|
+
node: true,
|
|
8
|
+
mocha: true,
|
|
9
|
+
es2022: true
|
|
10
|
+
},
|
|
11
|
+
rules: {
|
|
12
|
+
"@typescript-eslint/consistent-type-imports": "error"
|
|
13
|
+
}
|
|
14
|
+
};
|