hybrid 0.0.2 → 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 → LICENSE.md} +6 -6
- package/README.md +11 -0
- package/dist/cli.d.ts +1 -0
- package/dist/cli.js +547 -0
- package/dist/cli.js.map +1 -0
- package/dist/cli.mjs +577 -0
- package/dist/cli.mjs.map +1 -0
- package/package.json +46 -22
- package/readme.md +0 -13
package/{license → LICENSE.md}
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
|
|
1
|
+
MIT License
|
|
2
2
|
|
|
3
|
-
Copyright (c)
|
|
3
|
+
Copyright (c) [2023] [Hybrid INC]
|
|
4
4
|
|
|
5
5
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
6
|
of this software and associated documentation files (the "Software"), to deal
|
|
@@ -9,13 +9,13 @@ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
|
9
9
|
copies of the Software, and to permit persons to whom the Software is
|
|
10
10
|
furnished to do so, subject to the following conditions:
|
|
11
11
|
|
|
12
|
-
The above copyright notice and this permission notice shall be included in
|
|
13
|
-
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
14
|
|
|
15
15
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
16
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
17
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
18
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
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
|
|
21
|
-
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
package/dist/cli.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
package/dist/cli.js
ADDED
|
@@ -0,0 +1,547 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __defProps = Object.defineProperties;
|
|
5
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
6
|
+
var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
|
|
7
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
8
|
+
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
|
|
9
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
10
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
11
|
+
var __propIsEnum = Object.prototype.propertyIsEnumerable;
|
|
12
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
13
|
+
var __spreadValues = (a, b) => {
|
|
14
|
+
for (var prop in b || (b = {}))
|
|
15
|
+
if (__hasOwnProp.call(b, prop))
|
|
16
|
+
__defNormalProp(a, prop, b[prop]);
|
|
17
|
+
if (__getOwnPropSymbols)
|
|
18
|
+
for (var prop of __getOwnPropSymbols(b)) {
|
|
19
|
+
if (__propIsEnum.call(b, prop))
|
|
20
|
+
__defNormalProp(a, prop, b[prop]);
|
|
21
|
+
}
|
|
22
|
+
return a;
|
|
23
|
+
};
|
|
24
|
+
var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
|
|
25
|
+
var __commonJS = (cb, mod) => function __require() {
|
|
26
|
+
return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
|
|
27
|
+
};
|
|
28
|
+
var __copyProps = (to, from, except, desc) => {
|
|
29
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
30
|
+
for (let key of __getOwnPropNames(from))
|
|
31
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
32
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
33
|
+
}
|
|
34
|
+
return to;
|
|
35
|
+
};
|
|
36
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
37
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
38
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
39
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
40
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
41
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
42
|
+
mod
|
|
43
|
+
));
|
|
44
|
+
var __async = (__this, __arguments, generator) => {
|
|
45
|
+
return new Promise((resolve, reject) => {
|
|
46
|
+
var fulfilled = (value) => {
|
|
47
|
+
try {
|
|
48
|
+
step(generator.next(value));
|
|
49
|
+
} catch (e) {
|
|
50
|
+
reject(e);
|
|
51
|
+
}
|
|
52
|
+
};
|
|
53
|
+
var rejected = (value) => {
|
|
54
|
+
try {
|
|
55
|
+
step(generator.throw(value));
|
|
56
|
+
} catch (e) {
|
|
57
|
+
reject(e);
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
|
|
61
|
+
step((generator = generator.apply(__this, __arguments)).next());
|
|
62
|
+
});
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
// package.json
|
|
66
|
+
var require_package = __commonJS({
|
|
67
|
+
"package.json"(exports2, module2) {
|
|
68
|
+
module2.exports = {
|
|
69
|
+
name: "hybrid",
|
|
70
|
+
version: "0.1.0",
|
|
71
|
+
description: "Solidity + TypeScript Framework for Web3 Development",
|
|
72
|
+
author: "Ian Hunter <ian@ianh.xyz>",
|
|
73
|
+
homepage: "https://github.com/ian/hybrid#readme",
|
|
74
|
+
license: "ISC",
|
|
75
|
+
main: "dist/cli.js",
|
|
76
|
+
module: "dist/cli.mjs",
|
|
77
|
+
bin: {
|
|
78
|
+
hy: "dist/cli.mjs",
|
|
79
|
+
hybrid: "dist/cli.mjs"
|
|
80
|
+
},
|
|
81
|
+
files: [
|
|
82
|
+
"dist"
|
|
83
|
+
],
|
|
84
|
+
repository: {
|
|
85
|
+
type: "git",
|
|
86
|
+
url: "git+https://github.com/ian/hybrid.git"
|
|
87
|
+
},
|
|
88
|
+
scripts: {
|
|
89
|
+
clean: "rm -rf dist",
|
|
90
|
+
build: "tsup",
|
|
91
|
+
dev: "nodemon",
|
|
92
|
+
test: "node ./__tests__/cli.test.js"
|
|
93
|
+
},
|
|
94
|
+
bugs: {
|
|
95
|
+
url: "https://github.com/ian/hybrid/issues"
|
|
96
|
+
},
|
|
97
|
+
dependencies: {
|
|
98
|
+
"@hybrd/contracts": "^0.1.0",
|
|
99
|
+
"@hybrd/react": "^0.1.0",
|
|
100
|
+
bip39: "^3.1.0",
|
|
101
|
+
boxen: "^7.0.2",
|
|
102
|
+
chalk: "4.1.2",
|
|
103
|
+
chokidar: "^3.5.3",
|
|
104
|
+
commander: "^10.0.0",
|
|
105
|
+
"ethereum-private-key-to-address": "^0.0.7",
|
|
106
|
+
ethers: "^6.1.0",
|
|
107
|
+
figlet: "^1.5.2",
|
|
108
|
+
inquirer: "^9.1.4",
|
|
109
|
+
ora: "5.4.0",
|
|
110
|
+
viem: "^0.1.10"
|
|
111
|
+
},
|
|
112
|
+
devDependencies: {
|
|
113
|
+
"@types/inquirer": "^9.0.3",
|
|
114
|
+
"@types/node": "^18.14.6",
|
|
115
|
+
nodemon: "^2.0.21",
|
|
116
|
+
tsup: "^6.6.3",
|
|
117
|
+
tsx: "^3.12.3",
|
|
118
|
+
typescript: "^4.9.5"
|
|
119
|
+
},
|
|
120
|
+
gitHead: "4dc22eb383621ec5bcdb4989d123489b726af4e7"
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
// src/cli.ts
|
|
126
|
+
var import_commander = require("commander");
|
|
127
|
+
|
|
128
|
+
// src/lib/helpers.ts
|
|
129
|
+
var import_child_process = require("child_process");
|
|
130
|
+
var import_fs = __toESM(require("fs"));
|
|
131
|
+
var import_ora = __toESM(require("ora"));
|
|
132
|
+
function writeFile(path3, data) {
|
|
133
|
+
return __async(this, null, function* () {
|
|
134
|
+
return import_fs.default.writeFileSync(path3, data);
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
function cmd(_0, _1) {
|
|
138
|
+
return __async(this, arguments, function* (cmd2, args, opts = {
|
|
139
|
+
encoding: "utf8"
|
|
140
|
+
}) {
|
|
141
|
+
return new Promise((resolve, reject) => {
|
|
142
|
+
const install = (0, import_child_process.spawn)(cmd2, args, opts);
|
|
143
|
+
install.stdout.on("data", (data) => {
|
|
144
|
+
var _a;
|
|
145
|
+
(_a = opts.stdout) == null ? void 0 : _a.call(opts, data.toString());
|
|
146
|
+
});
|
|
147
|
+
install.stderr.on("data", (data) => {
|
|
148
|
+
var _a;
|
|
149
|
+
(_a = opts.stderr) == null ? void 0 : _a.call(opts, data.toString());
|
|
150
|
+
});
|
|
151
|
+
install.on("error", (error) => {
|
|
152
|
+
reject(error);
|
|
153
|
+
});
|
|
154
|
+
install.on("close", (code) => {
|
|
155
|
+
resolve(code);
|
|
156
|
+
});
|
|
157
|
+
});
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
function spinner(label, fn) {
|
|
161
|
+
return __async(this, null, function* () {
|
|
162
|
+
let spinner2;
|
|
163
|
+
if (label)
|
|
164
|
+
spinner2 = (0, import_ora.default)(label).start();
|
|
165
|
+
return fn().then(() => {
|
|
166
|
+
spinner2 == null ? void 0 : spinner2.succeed(`${label} ... DONE`);
|
|
167
|
+
}).catch((err) => {
|
|
168
|
+
spinner2 == null ? void 0 : spinner2.fail(`${label}`);
|
|
169
|
+
console.error(err);
|
|
170
|
+
});
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
// src/lib/foundry.ts
|
|
175
|
+
function build() {
|
|
176
|
+
return __async(this, arguments, function* (opts = {}) {
|
|
177
|
+
return new Promise((resolve, reject) => __async(this, null, function* () {
|
|
178
|
+
return cmd("forge", ["build", "--force"], __spreadProps(__spreadValues({}, opts), {
|
|
179
|
+
// hijack the stderr and reject if anything comes thru
|
|
180
|
+
stderr: (msg) => reject(msg)
|
|
181
|
+
})).then(resolve);
|
|
182
|
+
}));
|
|
183
|
+
});
|
|
184
|
+
}
|
|
185
|
+
function forgeDeploy(name, rpc, key) {
|
|
186
|
+
return __async(this, null, function* () {
|
|
187
|
+
const output = [];
|
|
188
|
+
const error = [];
|
|
189
|
+
yield cmd("forge", ["create", name, `--rpc-url`, rpc, "--private-key", key], {
|
|
190
|
+
stdout: (msg) => output.push(msg),
|
|
191
|
+
stderr: (err) => error.push(err)
|
|
192
|
+
});
|
|
193
|
+
const address = output.join("").match(/Deployed to: (0x.{40})/);
|
|
194
|
+
const hash = output.join("").match(/Transaction hash: (0x.{64})/);
|
|
195
|
+
return {
|
|
196
|
+
address: address ? address[1] : null,
|
|
197
|
+
hash: hash ? hash[1] : null
|
|
198
|
+
};
|
|
199
|
+
});
|
|
200
|
+
}
|
|
201
|
+
function anvil(mnemonic, forkUrl) {
|
|
202
|
+
return __async(this, null, function* () {
|
|
203
|
+
return new Promise((resolve) => {
|
|
204
|
+
cmd(
|
|
205
|
+
"anvil",
|
|
206
|
+
["--mnemonic", mnemonic, "--fork-url", forkUrl, "--chain-id", "1337"],
|
|
207
|
+
{
|
|
208
|
+
stdout: (str) => {
|
|
209
|
+
const keys = str.match(/0x.{64}/g);
|
|
210
|
+
const listens = str.match(/Listening on (.*?)\n/);
|
|
211
|
+
if (listens) {
|
|
212
|
+
const [host, port] = listens[1].split(":");
|
|
213
|
+
resolve({
|
|
214
|
+
host,
|
|
215
|
+
port,
|
|
216
|
+
keys
|
|
217
|
+
});
|
|
218
|
+
}
|
|
219
|
+
},
|
|
220
|
+
stderr: (str) => process.stderr.write(str)
|
|
221
|
+
}
|
|
222
|
+
);
|
|
223
|
+
});
|
|
224
|
+
});
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
// src/cmd/build.ts
|
|
228
|
+
function build2() {
|
|
229
|
+
return __async(this, null, function* () {
|
|
230
|
+
return spinner("Building contracts...", () => build());
|
|
231
|
+
});
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
// src/cmd/test.ts
|
|
235
|
+
var import_child_process2 = require("child_process");
|
|
236
|
+
function test() {
|
|
237
|
+
return __async(this, null, function* () {
|
|
238
|
+
return (0, import_child_process2.execSync)("forge test", { stdio: "inherit" });
|
|
239
|
+
});
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
// src/cmd/dev.ts
|
|
243
|
+
var import_bip39 = __toESM(require("bip39"));
|
|
244
|
+
var import_chokidar = __toESM(require("chokidar"));
|
|
245
|
+
var import_path = __toESM(require("path"));
|
|
246
|
+
var import_boxen = __toESM(require("boxen"));
|
|
247
|
+
var import_ora2 = __toESM(require("ora"));
|
|
248
|
+
|
|
249
|
+
// src/lib/builder.ts
|
|
250
|
+
var import_fs2 = __toESM(require("fs"));
|
|
251
|
+
var writeConfig = () => __async(void 0, null, function* () {
|
|
252
|
+
const contracts = yield listContracts(process.cwd() + "/contracts");
|
|
253
|
+
const abis = contracts.reduce((acc, filename) => {
|
|
254
|
+
const name = filename.replace(".sol", "");
|
|
255
|
+
acc[name] = `require("./out/${name}.sol/${name}.json").abi as Abi`;
|
|
256
|
+
return acc;
|
|
257
|
+
}, {});
|
|
258
|
+
return import_fs2.default.writeFileSync(
|
|
259
|
+
process.cwd() + "/.hybrid/index.ts",
|
|
260
|
+
`
|
|
261
|
+
import { Abi } from "abitype";
|
|
262
|
+
|
|
263
|
+
export const ABI = {
|
|
264
|
+
${Object.keys(abis).map((name) => `${name}: ${abis[name]}`).join(",\n ")}
|
|
265
|
+
};
|
|
266
|
+
`
|
|
267
|
+
);
|
|
268
|
+
});
|
|
269
|
+
var listContracts = (dir) => __async(void 0, null, function* () {
|
|
270
|
+
const files = yield import_fs2.default.readdirSync(dir);
|
|
271
|
+
return files.filter((f) => !f.match(/(t|test)\.sol$/));
|
|
272
|
+
});
|
|
273
|
+
|
|
274
|
+
// src/cmd/dev.ts
|
|
275
|
+
function dev() {
|
|
276
|
+
return __async(this, null, function* () {
|
|
277
|
+
const contractsDir = process.cwd() + "/contracts";
|
|
278
|
+
const forkUrl = "https://goerli.infura.io/v3/e6481145ca1442b7bf2a8444a8cd0fc8";
|
|
279
|
+
const mnemonic = import_bip39.default.generateMnemonic();
|
|
280
|
+
const [testnet] = yield Promise.all([
|
|
281
|
+
anvil(mnemonic, forkUrl)
|
|
282
|
+
// @todo - some sort of dev interface
|
|
283
|
+
]);
|
|
284
|
+
console.log();
|
|
285
|
+
console.log(
|
|
286
|
+
(0, import_boxen.default)(
|
|
287
|
+
`
|
|
288
|
+
Dev UI | http://127.0.0.1:8580
|
|
289
|
+
RPC Node | http://${testnet.host}:${testnet.port}
|
|
290
|
+
----------+----------------------
|
|
291
|
+
Docs | https://hybrid.dev
|
|
292
|
+
Watching | ${"./" + import_path.default.relative(process.cwd(), contractsDir)}
|
|
293
|
+
`.trim(),
|
|
294
|
+
{
|
|
295
|
+
title: "Hybrid Dev Server",
|
|
296
|
+
titleAlignment: "left",
|
|
297
|
+
borderColor: "greenBright",
|
|
298
|
+
padding: 1,
|
|
299
|
+
margin: 0.5,
|
|
300
|
+
borderStyle: "double"
|
|
301
|
+
}
|
|
302
|
+
)
|
|
303
|
+
);
|
|
304
|
+
console.log();
|
|
305
|
+
console.log("Keys:");
|
|
306
|
+
console.log(testnet.keys.join("\n"));
|
|
307
|
+
console.log();
|
|
308
|
+
import_chokidar.default.watch(contractsDir).on("all", (event, file) => {
|
|
309
|
+
switch (event) {
|
|
310
|
+
case "change":
|
|
311
|
+
if (!file.endsWith(".sol"))
|
|
312
|
+
return;
|
|
313
|
+
if (file.endsWith(".test.sol")) {
|
|
314
|
+
return;
|
|
315
|
+
} else {
|
|
316
|
+
const filename = import_path.default.basename(file);
|
|
317
|
+
const name = filename.replace(".sol", "");
|
|
318
|
+
let spinner2 = (0, import_ora2.default)("Deploying " + name).start();
|
|
319
|
+
forgeDeploy(name, "http://localhost:8545", testnet.keys[0]).then(
|
|
320
|
+
({ address }) => {
|
|
321
|
+
writeConfig();
|
|
322
|
+
spinner2.succeed(name + " deployed to " + address);
|
|
323
|
+
}
|
|
324
|
+
);
|
|
325
|
+
}
|
|
326
|
+
break;
|
|
327
|
+
default:
|
|
328
|
+
break;
|
|
329
|
+
}
|
|
330
|
+
});
|
|
331
|
+
});
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
// src/cmd/init.ts
|
|
335
|
+
var import_chalk = __toESM(require("chalk"));
|
|
336
|
+
var import_fs3 = __toESM(require("fs"));
|
|
337
|
+
var import_path2 = __toESM(require("path"));
|
|
338
|
+
var import_inquirer = __toESM(require("inquirer"));
|
|
339
|
+
function init() {
|
|
340
|
+
return __async(this, null, function* () {
|
|
341
|
+
const mdVersion = require_package().version;
|
|
342
|
+
console.log(`
|
|
343
|
+
|
|
344
|
+
\u2588\u2588\u2584
|
|
345
|
+
\u2584\u2588\u2584 \u2580\u2588\u2588\u2584
|
|
346
|
+
\u2584\u2588\u2588 \u2580\u2588\u2588 \u2588\u2588 \u2580\u2580 \u2593\u2588 \u2593\u2588
|
|
347
|
+
\u2588\u2588 \u2584 \u2580\u2588\u2588 \u2588\u2588\u2584 \u2590\u2588\u2588\u2588\u2588\u2584\u2593\u2588\u2588\u2593 \u2593\u2588 \u2593\u2588\u2588\u2588\u2588\u2584 \u2593\u2588\u2588\u2588 \u2584\u2588\u2588\u2588\u2588\u2588\u2588 \u2593\u2588\u2588\u258C \u2584\u2593\u2588\u2588\u2588\u2584 \u2593\u2588\u2593\u2588\u2588\u2588\u2584
|
|
348
|
+
\u2593\u2588 \u2593\u2588\u2580 \u2588\u2588 \u2588\u2588 \u2590\u2588 \u2588\u258C \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u258C \u2593\u2588 \u2588\u2588 \u2588\u2588 \u2593\u2588 \u2590\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588
|
|
349
|
+
\u2588\u2588 \u2588\u2588 \u2590\u2588\u2580 \u2593\u2588 \u2590\u2588 \u2588\u258C \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u258C \u2593\u2588 \u2580\u2588\u2584 \u2584\u2588\u2588 \u2593\u2588 \u2590\u2588\u2584 \u2588\u2588 \u2588\u2588\u2584 \u2588\u2588
|
|
350
|
+
\u2590\u2588\u258C \u2590\u2588\u2588\u2584\u2584\u2593\u2588\u2580 \u2588\u2588 \u2580 \u2580\u2580 \u2580\u2580 \u2580\u2580 \u2580\u2580 \u2580 \u2580\u2580 \u2580\u2580\u2580\u2580\u2580\u2580 \u2580\u2580 \u2580\u2580\u2580\u2580 \u2588\u2588\u2580\u2580\u2580\u2580
|
|
351
|
+
\u2580\u2588\u2588\u2584 \u2584\u2588\u2580 \u2588\u2588
|
|
352
|
+
\u2580\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2580 The NFT Development Framework.
|
|
353
|
+
|
|
354
|
+
|
|
355
|
+
Installing Hybrid v${mdVersion} ...
|
|
356
|
+
`);
|
|
357
|
+
if (!import_fs3.default.existsSync("./package.json")) {
|
|
358
|
+
console.error(
|
|
359
|
+
import_chalk.default.red("Error: No package.json found. Are you in the right directory?")
|
|
360
|
+
);
|
|
361
|
+
process.exit();
|
|
362
|
+
}
|
|
363
|
+
const pkgManager = import_fs3.default.existsSync("./yarn.lock") ? "yarn" : import_fs3.default.existsSync("./pnpm-lock.yaml") ? "pnpm" : "npm";
|
|
364
|
+
const cwd = process.cwd();
|
|
365
|
+
const answers = yield import_inquirer.default.prompt([
|
|
366
|
+
{
|
|
367
|
+
name: "chain",
|
|
368
|
+
type: "list",
|
|
369
|
+
choices: [
|
|
370
|
+
"Ethereum",
|
|
371
|
+
"Polygon",
|
|
372
|
+
"Arbitrum",
|
|
373
|
+
"Binance Smart Chain",
|
|
374
|
+
"Base"
|
|
375
|
+
]
|
|
376
|
+
}
|
|
377
|
+
]);
|
|
378
|
+
yield spinner(
|
|
379
|
+
"Installing Hybrid dependencies",
|
|
380
|
+
() => __async(this, null, function* () {
|
|
381
|
+
return cmd(pkgManager, ["add", "hybrid", "hybrid/react"], {
|
|
382
|
+
cwd
|
|
383
|
+
});
|
|
384
|
+
})
|
|
385
|
+
);
|
|
386
|
+
yield spinner("Adding smart contracts", () => __async(this, null, function* () {
|
|
387
|
+
const solidityPragma = "pragma solidity ^0.8.13";
|
|
388
|
+
yield cmd("sh", ["-c", "curl -L https://foundry.paradigm.xyz | bash"], {
|
|
389
|
+
cwd
|
|
390
|
+
});
|
|
391
|
+
yield cmd("foundryup", [], {
|
|
392
|
+
cwd
|
|
393
|
+
});
|
|
394
|
+
yield writeFile(
|
|
395
|
+
[cwd, "foundry.toml"].join("/"),
|
|
396
|
+
`# See more config options https://github.com/foundry-rs/foundry/tree/master/config
|
|
397
|
+
|
|
398
|
+
[profile.default]
|
|
399
|
+
src = './contracts'
|
|
400
|
+
test = './contracts'
|
|
401
|
+
cache = true
|
|
402
|
+
cache_path = '.hybrid/cache'
|
|
403
|
+
out = '.hybrid/out'
|
|
404
|
+
libs = ["node_modules"]
|
|
405
|
+
gas_reports = ["*"]`
|
|
406
|
+
);
|
|
407
|
+
yield import_fs3.default.mkdirSync([cwd, "contracts"].join("/"), { recursive: true });
|
|
408
|
+
yield writeFile(
|
|
409
|
+
[cwd, "contracts/MyNFT.sol"].join("/"),
|
|
410
|
+
`// SPDX-License-Identifier: UNLICENSED
|
|
411
|
+
${solidityPragma};
|
|
412
|
+
|
|
413
|
+
import "erc721a/contracts/ERC721A.sol";
|
|
414
|
+
|
|
415
|
+
contract MyNFT is ERC721A {
|
|
416
|
+
constructor() ERC721A("My NFT", "NFT") {}
|
|
417
|
+
|
|
418
|
+
// We prefer tokenIds to start at 1
|
|
419
|
+
function _startTokenId() internal pure override returns (uint256) {
|
|
420
|
+
return 1;
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
function mint(uint256 quantity) external payable {
|
|
424
|
+
_mint(msg.sender, quantity);
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
/**
|
|
428
|
+
* @dev override both ERC721A and ERC2981
|
|
429
|
+
*/
|
|
430
|
+
function supportsInterface(
|
|
431
|
+
bytes4 interfaceId
|
|
432
|
+
) public view override(ERC721A) returns (bool) {
|
|
433
|
+
return ERC721A.supportsInterface(interfaceId);
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
`
|
|
437
|
+
);
|
|
438
|
+
yield writeFile(
|
|
439
|
+
[cwd, "contracts/MyNFT.test.sol"].join("/"),
|
|
440
|
+
`// SPDX-License-Identifier: UNLICENSED
|
|
441
|
+
${solidityPragma};
|
|
442
|
+
|
|
443
|
+
import "forge-std/console.sol";
|
|
444
|
+
import "forge-std/Test.sol";
|
|
445
|
+
|
|
446
|
+
import "./MyNFT.sol";
|
|
447
|
+
|
|
448
|
+
contract MyContractTest is Test {
|
|
449
|
+
MyNFT public mock;
|
|
450
|
+
|
|
451
|
+
function setUp() public {
|
|
452
|
+
mock = new MyNFT();
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
function testMint() public {
|
|
456
|
+
address minter = makeAddr("minter");
|
|
457
|
+
assertEq(mock.balanceOf(minter), 0);
|
|
458
|
+
vm.prank(minter);
|
|
459
|
+
mock.mint(1);
|
|
460
|
+
assertEq(mock.balanceOf(minter), 1);
|
|
461
|
+
}
|
|
462
|
+
}
|
|
463
|
+
`
|
|
464
|
+
);
|
|
465
|
+
}));
|
|
466
|
+
yield spinner(
|
|
467
|
+
"Adding hybrid.config.js",
|
|
468
|
+
() => __async(this, null, function* () {
|
|
469
|
+
return writeFile(
|
|
470
|
+
[cwd, "hybrid.config.js"].join("/"),
|
|
471
|
+
`
|
|
472
|
+
module.exports = {
|
|
473
|
+
token: "1234567890",
|
|
474
|
+
chain: "${answers.chain}",
|
|
475
|
+
}
|
|
476
|
+
`
|
|
477
|
+
);
|
|
478
|
+
})
|
|
479
|
+
);
|
|
480
|
+
console.log();
|
|
481
|
+
console.log(
|
|
482
|
+
import_chalk.default.green.bold("Success!"),
|
|
483
|
+
`Hybrid Installed`,
|
|
484
|
+
import_path2.default.relative(process.cwd(), cwd)
|
|
485
|
+
);
|
|
486
|
+
});
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
// src/cmd/deploy.ts
|
|
490
|
+
var import_inquirer2 = __toESM(require("inquirer"));
|
|
491
|
+
function deploy(contract, target) {
|
|
492
|
+
return __async(this, null, function* () {
|
|
493
|
+
const { key } = yield import_inquirer2.default.prompt([
|
|
494
|
+
{
|
|
495
|
+
name: "key",
|
|
496
|
+
message: "Private Key",
|
|
497
|
+
type: "input"
|
|
498
|
+
}
|
|
499
|
+
]);
|
|
500
|
+
switch (target) {
|
|
501
|
+
case "local":
|
|
502
|
+
return forgeDeploy(contract, "http://localhost:8545", key);
|
|
503
|
+
default:
|
|
504
|
+
throw new Error("Unknown target" + target);
|
|
505
|
+
}
|
|
506
|
+
});
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
// src/cli.ts
|
|
510
|
+
var import_boxen2 = __toESM(require("boxen"));
|
|
511
|
+
if (process.argv[2] === "init") {
|
|
512
|
+
init();
|
|
513
|
+
} else {
|
|
514
|
+
const program = new import_commander.Command();
|
|
515
|
+
program.name("mint").description("The Hybrid NFT Development Framework").version(require_package().version);
|
|
516
|
+
program.command("build").description("Builds smart contracts and generates TS types").action(() => {
|
|
517
|
+
build2();
|
|
518
|
+
});
|
|
519
|
+
program.command("test").description("Run smart contract tests").action(() => {
|
|
520
|
+
test();
|
|
521
|
+
});
|
|
522
|
+
program.command("dev").description("Starts hybrid in development mode").action(() => {
|
|
523
|
+
dev();
|
|
524
|
+
});
|
|
525
|
+
program.command("deploy").description("Deploy smart contracts").argument("<contract>", "Contract name").argument("<target>", "Deploy target [test|prod]").action((contract, target) => __async(exports, null, function* () {
|
|
526
|
+
yield deploy(contract, target).then(({ address, hash }) => {
|
|
527
|
+
console.log();
|
|
528
|
+
console.log(
|
|
529
|
+
(0, import_boxen2.default)(
|
|
530
|
+
`Address: ${address}
|
|
531
|
+
Tx Hash: ${hash}`,
|
|
532
|
+
{
|
|
533
|
+
title: `Contract ${contract} Deployed to ${target}`,
|
|
534
|
+
titleAlignment: "left",
|
|
535
|
+
borderColor: "yellowBright",
|
|
536
|
+
padding: 1,
|
|
537
|
+
margin: 0.5,
|
|
538
|
+
borderStyle: "double"
|
|
539
|
+
}
|
|
540
|
+
)
|
|
541
|
+
);
|
|
542
|
+
console.log();
|
|
543
|
+
});
|
|
544
|
+
}));
|
|
545
|
+
program.parse();
|
|
546
|
+
}
|
|
547
|
+
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../package.json","../src/cli.ts","../src/lib/helpers.ts","../src/lib/foundry.ts","../src/cmd/build.ts","../src/cmd/test.ts","../src/cmd/dev.ts","../src/lib/builder.ts","../src/cmd/init.ts","../src/cmd/deploy.ts"],"sourcesContent":["{\n \"name\": \"hybrid\",\n \"version\": \"0.1.0\",\n \"description\": \"Solidity + TypeScript Framework for Web3 Development\",\n \"author\": \"Ian Hunter <ian@ianh.xyz>\",\n \"homepage\": \"https://github.com/ian/hybrid#readme\",\n \"license\": \"ISC\",\n \"main\": \"dist/cli.js\",\n \"module\": \"dist/cli.mjs\",\n \"bin\": {\n \"hy\": \"dist/cli.mjs\",\n \"hybrid\": \"dist/cli.mjs\"\n },\n \"files\": [\n \"dist\"\n ],\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"git+https://github.com/ian/hybrid.git\"\n },\n \"scripts\": {\n \"clean\": \"rm -rf dist\",\n \"build\": \"tsup\",\n \"dev\": \"nodemon\",\n \"test\": \"node ./__tests__/cli.test.js\"\n },\n \"bugs\": {\n \"url\": \"https://github.com/ian/hybrid/issues\"\n },\n \"dependencies\": {\n \"@hybrd/contracts\": \"^0.1.0\",\n \"@hybrd/react\": \"^0.1.0\",\n \"bip39\": \"^3.1.0\",\n \"boxen\": \"^7.0.2\",\n \"chalk\": \"4.1.2\",\n \"chokidar\": \"^3.5.3\",\n \"commander\": \"^10.0.0\",\n \"ethereum-private-key-to-address\": \"^0.0.7\",\n \"ethers\": \"^6.1.0\",\n \"figlet\": \"^1.5.2\",\n \"inquirer\": \"^9.1.4\",\n \"ora\": \"5.4.0\",\n \"viem\": \"^0.1.10\"\n },\n \"devDependencies\": {\n \"@types/inquirer\": \"^9.0.3\",\n \"@types/node\": \"^18.14.6\",\n \"nodemon\": \"^2.0.21\",\n \"tsup\": \"^6.6.3\",\n \"tsx\": \"^3.12.3\",\n \"typescript\": \"^4.9.5\"\n },\n \"gitHead\": \"4dc22eb383621ec5bcdb4989d123489b726af4e7\"\n}\n","#!/usr/bin/env node\n\nimport { Command } from \"commander\"\nimport { build } from \"./cmd/build\"\nimport { test } from \"./cmd/test\"\nimport { dev } from \"./cmd/dev\"\nimport { init } from \"./cmd/init\"\nimport { deploy } from \"./cmd/deploy\"\nimport boxen from \"boxen\"\n\nif (process.argv[2] === \"init\") {\n // Handle init separately, best to not surface this in the help menu\n init()\n} else {\n const program = new Command()\n program\n .name(\"mint\")\n .description(\"The Hybrid NFT Development Framework\")\n .version(require(\"../package.json\").version)\n\n program\n .command(\"build\")\n .description(\"Builds smart contracts and generates TS types\")\n .action((/* opts */) => {\n build()\n })\n\n program\n .command(\"test\")\n .description(\"Run smart contract tests\")\n .action((/* opts */) => {\n test()\n })\n\n program\n .command(\"dev\")\n .description(\"Starts hybrid in development mode\")\n .action((/* opts */) => {\n dev()\n })\n\n program\n .command(\"deploy\")\n .description(\"Deploy smart contracts\")\n .argument(\"<contract>\", \"Contract name\")\n .argument(\"<target>\", \"Deploy target [test|prod]\")\n .action(async (contract, target) => {\n await deploy(contract, target).then(({ address, hash }) => {\n console.log()\n console.log(\n boxen(\n `Address: ${address}\nTx Hash: ${hash}`,\n {\n title: `Contract ${contract} Deployed to ${target}`,\n titleAlignment: \"left\",\n borderColor: \"yellowBright\",\n padding: 1,\n margin: 0.5,\n borderStyle: \"double\"\n }\n )\n )\n console.log()\n })\n })\n\n program.parse()\n}\n","import { spawn } from \"child_process\"\nimport fs from \"fs\"\nimport ora, { Ora } from \"ora\"\n\nexport async function writeFile(path: string, data: string) {\n return fs.writeFileSync(path, data)\n}\n\nexport type SpawnOpts = {\n cwd?: string\n encoding?: string\n stdout?: (data: string) => void\n stderr?: (data: string) => void\n}\n\nexport async function cmd(\n cmd: string,\n args: string[],\n opts: SpawnOpts = {\n encoding: \"utf8\"\n }\n) {\n return new Promise((resolve, reject) => {\n const install = spawn(cmd, args, opts)\n\n install.stdout.on(\"data\", (data: any) => {\n opts.stdout?.(data.toString())\n })\n\n install.stderr.on(\"data\", (data: any) => {\n opts.stderr?.(data.toString())\n })\n\n install.on(\"error\", (error: Error) => {\n reject(error)\n })\n\n install.on(\"close\", (code: number) => {\n resolve(code)\n })\n })\n}\n\nexport async function spinner(label: string, fn: () => Promise<any>) {\n let spinner: Ora\n if (label) spinner = ora(label).start()\n return fn()\n .then(() => {\n spinner?.succeed(`${label} ... DONE`)\n })\n .catch((err) => {\n spinner?.fail(`${label}`)\n console.error(err)\n })\n}\n","import { SpawnOpts, cmd } from \"./helpers\"\n\nexport type BuildOpts = {\n // todo - add more options\n} & SpawnOpts\n\nexport async function build(opts: BuildOpts = {}) {\n return new Promise(async (resolve, reject) => {\n return cmd(\"forge\", [\"build\", \"--force\"], {\n ...opts,\n // hijack the stderr and reject if anything comes thru\n stderr: (msg) => reject(msg)\n }).then(resolve)\n })\n}\n\nexport async function forgeDeploy(name: string, rpc: string, key: string) {\n const output: string[] = []\n const error: string[] = []\n\n await cmd(\"forge\", [\"create\", name, `--rpc-url`, rpc, \"--private-key\", key], {\n stdout: (msg) => output.push(msg),\n stderr: (err) => error.push(err)\n })\n\n const address = output.join(\"\").match(/Deployed to: (0x.{40})/)\n const hash = output.join(\"\").match(/Transaction hash: (0x.{64})/)\n\n return {\n address: address ? address[1] : null,\n hash: hash ? hash[1] : null\n }\n}\n\ntype AnvilListening = {\n host: string\n port: string\n keys: `0x${string}`[]\n}\n\nexport async function anvil(\n mnemonic: string,\n forkUrl: string\n): Promise<AnvilListening> {\n return new Promise((resolve) => {\n cmd(\n \"anvil\",\n [\"--mnemonic\", mnemonic, \"--fork-url\", forkUrl, \"--chain-id\", \"1337\"],\n {\n stdout: (str) => {\n const keys = str.match(/0x.{64}/g) as `0x${string}`[]\n const listens = str.match(/Listening on (.*?)\\n/)\n\n if (listens) {\n const [host, port] = listens[1].split(\":\")\n resolve({\n host,\n port,\n keys\n })\n }\n },\n stderr: (str) => process.stderr.write(str)\n }\n )\n })\n}\n","import * as foundry from \"../lib/foundry\"\nimport { spinner } from \"../lib/helpers\"\n\nexport async function build() {\n return spinner(\"Building contracts...\", () => foundry.build())\n}\n","import { execSync } from \"child_process\"\n\nexport async function test() {\n return execSync(\"forge test\", { stdio: \"inherit\" })\n}\n","import bip39 from \"bip39\"\nimport chokidar from \"chokidar\"\nimport path from \"path\"\nimport { anvil, forgeDeploy } from \"../lib/foundry\"\nimport boxen from \"boxen\"\nimport ora from \"ora\"\nimport { writeConfig } from \"../lib/builder\"\n\n// @todo\n// [] - switch to config object for paths\n\nexport async function dev() {\n const contractsDir = process.cwd() + \"/contracts\"\n const forkUrl = \"https://goerli.infura.io/v3/e6481145ca1442b7bf2a8444a8cd0fc8\"\n const mnemonic = bip39.generateMnemonic()\n\n const [testnet] = await Promise.all([\n anvil(mnemonic, forkUrl)\n // @todo - some sort of dev interface\n ])\n\n console.log()\n console.log(\n boxen(\n `\nDev UI | http://127.0.0.1:8580\nRPC Node | http://${testnet.host}:${testnet.port}\n----------+----------------------\nDocs | https://hybrid.dev\nWatching | ${\"./\" + path.relative(process.cwd(), contractsDir)}\n`.trim(),\n {\n title: \"Hybrid Dev Server\",\n titleAlignment: \"left\",\n borderColor: \"greenBright\",\n\n padding: 1,\n margin: 0.5,\n borderStyle: \"double\"\n }\n )\n )\n console.log()\n console.log(\"Keys:\")\n console.log(testnet.keys.join(\"\\n\"))\n console.log()\n\n // listCompiled().then((files) => {\n // return files.map((file) =>\n // readCompiled(file).then(({ abi, bytecode }) =>\n // deployContract({\n // privateKey: testnet.keys[0],\n // abi,\n // bytecode\n // }).then(console.log)\n // )\n // )\n // })\n\n chokidar.watch(contractsDir).on(\"all\", (event, file) => {\n switch (event) {\n // case \"add\":\n // console.log(event, path)\n // break\n\n case \"change\":\n if (!file.endsWith(\".sol\")) return\n if (file.endsWith(\".test.sol\")) {\n // console.log(\"Skipping test file\", file)\n return\n } else {\n // build().then(() => {\n\n // })\n\n const filename = path.basename(file)\n const name = filename.replace(\".sol\", \"\")\n\n let spinner = ora(\"Deploying \" + name).start()\n forgeDeploy(name, \"http://localhost:8545\", testnet.keys[0]).then(\n ({ address }) => {\n writeConfig()\n spinner.succeed(name + \" deployed to \" + address)\n }\n )\n\n // .then(() => readCompiled(file))\n // .then(\n // ({ abi, bytecode }) =>\n // forgeDeploy(contract, \"http://localhost:8545\", key)\n // // deployContract({\n // // privateKey: testnet.keys[0],\n // // abi,\n // // bytecode\n // // }).then(console.log)\n // )\n }\n\n break\n default:\n // console.log(event, path)\n break\n }\n })\n}\n\n// const readCompiled = async (file: string) => {\n// const distDir = process.cwd() + \"/.hybrid/out\"\n// const filename = path.basename(file)\n// const name = filename.replace(\".sol\", \"\")\n// const contents = await fs\n// .readFileSync(`${distDir}/${filename}/${name}.json`)\n// .toString()\n// return JSON.parse(contents)\n// }\n","import fs from \"fs\"\n\n// import { Abi } from \"abitype\";\n\n// export const ABI = {\n// MyNFT: require(\"./out/MyNFT.sol/MyNFT.json\").abi as Abi,\n// };\n\nexport const writeConfig = async () => {\n const contracts = await listContracts(process.cwd() + \"/contracts\")\n\n const abis = contracts.reduce((acc, filename: string) => {\n const name = filename.replace(\".sol\", \"\")\n acc[name] = `require(\"./out/${name}.sol/${name}.json\").abi as Abi`\n return acc\n }, {})\n\n return fs.writeFileSync(\n process.cwd() + \"/.hybrid/index.ts\",\n `\nimport { Abi } from \"abitype\";\n\nexport const ABI = {\n ${Object.keys(abis)\n .map((name) => `${name}: ${abis[name]}`)\n .join(\",\\n \")}\n};\n `\n )\n}\n\nconst listContracts = async (dir) => {\n const files = await fs.readdirSync(dir)\n return files.filter((f) => !f.match(/(t|test)\\.sol$/))\n}\n","import chalk from \"chalk\"\nimport fs from \"fs\"\nimport path from \"path\"\nimport inquirer from \"inquirer\"\nimport { cmd, spinner, writeFile } from \"../lib/helpers\"\n\nexport async function init() {\n const mdVersion = require(\"../../package.json\").version\n\n console.log(`\n\n ██▄\n ▄█▄ ▀██▄\n ▄██ ▀██ ██ ▀▀ ▓█ ▓█\n ██ ▄ ▀██ ██▄ ▐████▄▓██▓ ▓█ ▓████▄ ▓███ ▄██████ ▓██▌ ▄▓███▄ ▓█▓███▄\n ▓█ ▓█▀ ██ ██ ▐█ █▌ ██ ██ ██ █▌ ▓█ ██ ██ ▓█ ▐█ ██ ██ ██\n ██ ██ ▐█▀ ▓█ ▐█ █▌ ██ ██ ██ █▌ ▓█ ▀█▄ ▄██ ▓█ ▐█▄ ██ ██▄ ██\n ▐█▌ ▐██▄▄▓█▀ ██ ▀ ▀▀ ▀▀ ▀▀ ▀▀ ▀ ▀▀ ▀▀▀▀▀▀ ▀▀ ▀▀▀▀ ██▀▀▀▀\n ▀██▄ ▄█▀ ██\n ▀███████▀ The NFT Development Framework.\n\n\nInstalling Hybrid v${mdVersion} ...\n`)\n\n if (!fs.existsSync(\"./package.json\")) {\n console.error(\n chalk.red(\"Error: No package.json found. Are you in the right directory?\")\n )\n process.exit()\n }\n\n const pkgManager = fs.existsSync(\"./yarn.lock\")\n ? \"yarn\"\n : fs.existsSync(\"./pnpm-lock.yaml\")\n ? \"pnpm\"\n : \"npm\"\n\n const cwd = process.cwd()\n const answers = await inquirer.prompt([\n {\n name: \"chain\",\n type: \"list\",\n choices: [\n \"Ethereum\",\n \"Polygon\",\n \"Arbitrum\",\n \"Binance Smart Chain\",\n \"Base\"\n ]\n }\n ])\n\n await spinner(\"Installing Hybrid dependencies\", async () =>\n cmd(pkgManager, [\"add\", \"hybrid\", \"hybrid/react\"], {\n cwd\n })\n )\n\n await spinner(\"Adding smart contracts\", async () => {\n const solidityPragma = \"pragma solidity ^0.8.13\"\n\n await cmd(\"sh\", [\"-c\", \"curl -L https://foundry.paradigm.xyz | bash\"], {\n cwd\n })\n\n await cmd(\"foundryup\", [], {\n cwd\n })\n\n await writeFile(\n [cwd, \"foundry.toml\"].join(\"/\"),\n `# See more config options https://github.com/foundry-rs/foundry/tree/master/config\n\n[profile.default]\nsrc = './contracts'\ntest = './contracts'\ncache = true\ncache_path = '.hybrid/cache'\nout = '.hybrid/out'\nlibs = [\"node_modules\"]\ngas_reports = [\"*\"]`\n )\n\n await fs.mkdirSync([cwd, \"contracts\"].join(\"/\"), { recursive: true })\n\n await writeFile(\n [cwd, \"contracts/MyNFT.sol\"].join(\"/\"),\n `// SPDX-License-Identifier: UNLICENSED\n${solidityPragma};\n\nimport \"erc721a/contracts/ERC721A.sol\";\n\ncontract MyNFT is ERC721A {\n\tconstructor() ERC721A(\"My NFT\", \"NFT\") {}\n\n\t// We prefer tokenIds to start at 1\n\tfunction _startTokenId() internal pure override returns (uint256) {\n\t\treturn 1;\n\t}\n\n\tfunction mint(uint256 quantity) external payable {\n\t\t_mint(msg.sender, quantity);\n\t}\n\n\t/**\n\t * @dev override both ERC721A and ERC2981\n\t */\n\tfunction supportsInterface(\n\t\tbytes4 interfaceId\n\t) public view override(ERC721A) returns (bool) {\n\t\treturn ERC721A.supportsInterface(interfaceId);\n\t}\n}\n `\n )\n\n await writeFile(\n [cwd, \"contracts/MyNFT.test.sol\"].join(\"/\"),\n `// SPDX-License-Identifier: UNLICENSED\n${solidityPragma};\n\nimport \"forge-std/console.sol\";\nimport \"forge-std/Test.sol\";\n\nimport \"./MyNFT.sol\";\n\ncontract MyContractTest is Test {\n\tMyNFT public mock;\n\n\tfunction setUp() public {\n\t\tmock = new MyNFT();\n\t}\n\n\tfunction testMint() public {\n\t\taddress minter = makeAddr(\"minter\");\n\t\tassertEq(mock.balanceOf(minter), 0);\n\t\tvm.prank(minter);\n\t\tmock.mint(1);\n\t\tassertEq(mock.balanceOf(minter), 1);\n\t}\n}\n `\n )\n })\n\n await spinner(\"Adding hybrid.config.js\", async () =>\n writeFile(\n [cwd, \"hybrid.config.js\"].join(\"/\"),\n `\nmodule.exports = {\n token: \"1234567890\",\n chain: \"${answers.chain}\",\n}\n `\n )\n )\n\n console.log()\n console.log(\n chalk.green.bold(\"Success!\"),\n `Hybrid Installed`,\n path.relative(process.cwd(), cwd)\n )\n}\n","import inquirer from \"inquirer\"\nimport { cmd } from \"../lib/helpers\"\nimport { forgeDeploy } from \"../lib/foundry\"\n\nexport async function deploy(contract: string, target: string) {\n // \"contracts:goerli\": \"forge create contracts/src/MintingTest.sol:MintingTest --constructor-args-path ./contracts/.args.goerli --verify --etherscan-api-key $ETHERSCAN_API_KEY --chain goerli --rpc-url $GOERLI_RPC_URL --interactive\",\n // \"contracts:mainnet\": \"forge create contracts/src/AerialExplorers.sol:AerialExplorers --gas-limit 3000000 --constructor-args-path ./contracts/.args.mainnet --verify --etherscan-api-key $ETHERSCAN_API_KEY --chain mainnet --rpc-url $MAINNET_RPC_URL --interactive\",\n\n const { key } = await inquirer.prompt([\n {\n name: \"key\",\n message: \"Private Key\",\n type: \"input\"\n }\n ])\n\n switch (target) {\n case \"local\":\n return forgeDeploy(contract, \"http://localhost:8545\", key)\n default:\n throw new Error(\"Unknown target\" + target)\n }\n}\n"],"mappings":"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","names":["exports","module","path","fs","cmd","spinner","ora","build","import_child_process","import_ora","import_fs","fs","bip39","boxen","path","chokidar","spinner","ora","import_fs","import_path","fs","chalk","inquirer","path","import_inquirer","inquirer","import_boxen","build","boxen"]}
|