@latticexyz/cli 2.0.0-alpha.78 → 2.0.0-alpha.8
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/dist/{chunk-TPZUS44H.js → chunk-6V563IAZ.js} +5 -5
- package/dist/{chunk-O6HOO6WA.js → chunk-L4YLJHLJ.js} +1 -9
- package/dist/{chunk-TLEAEDUA.js → chunk-QAJBBYA2.js} +357 -224
- package/dist/{chunk-KPBNUPK6.js → chunk-SKNB74MT.js} +155 -159
- package/dist/chunk-VQTZJIFF.js +353 -0
- package/dist/{chunk-DO7OWTMM.js → chunk-WZFXLDPK.js} +7 -9
- package/dist/{chunk-XUNWAEP7.js → chunk-YL4GJLLL.js} +5345 -6628
- package/dist/index.d.ts +2 -4
- package/dist/index.js +0 -22
- package/dist/mud.js +311 -318
- package/dist/mud2.js +7 -9
- package/dist/render-solidity/index.d.ts +2 -3
- package/dist/render-solidity/index.js +3 -4
- package/dist/render-ts/index.d.ts +2 -3
- package/dist/render-ts/index.js +3 -4
- package/dist/utils/deprecated/index.js +2 -2
- package/dist/utils/index.d.ts +3 -15
- package/dist/utils/index.js +4 -15
- package/package.json +36 -37
- package/src/commands/deploy-v2.ts +8 -4
- package/src/commands/deprecated/test.ts +1 -1
- package/src/commands/gas-report.ts +54 -55
- package/src/commands/set-version.ts +39 -10
- package/src/commands/tablegen.ts +1 -1
- package/src/commands/tsgen.ts +1 -1
- package/src/commands/worldgen.ts +1 -2
- package/src/contracts/BulkUpload.sol +13 -20
- package/src/contracts/Deploy.sol +3 -3
- package/src/contracts/LibDeploy.sol +1 -1
- package/src/contracts/LibDeployStub.sol +1 -1
- package/src/index.ts +1 -15
- package/src/render-solidity/common.ts +4 -4
- package/src/render-solidity/renderTypesFromConfig.ts +1 -1
- package/src/render-solidity/tableOptions.ts +2 -2
- package/src/render-solidity/tablegen.ts +1 -1
- package/src/render-solidity/types.ts +1 -1
- package/src/render-solidity/userType.ts +1 -2
- package/src/render-solidity/worldgen.ts +3 -3
- package/src/render-ts/recsV1TableOptions.ts +2 -2
- package/src/render-ts/renderRecsV1Tables.ts +2 -2
- package/src/render-ts/tsgen.ts +1 -1
- package/src/render-ts/types.ts +1 -1
- package/src/utils/contractToInterface.ts +1 -1
- package/src/utils/deploy-v2.ts +79 -78
- package/src/utils/errors.ts +3 -23
- package/dist/chunk-5NC2OON2.js +0 -164
- package/dist/chunk-FFY7VTYB.js +0 -14358
- package/dist/chunk-MN3HYFJK.js +0 -442
- package/dist/config/index.d.ts +0 -409
- package/dist/config/index.js +0 -85
- package/dist/parseStoreConfig-8aa69ac9.d.ts +0 -377
- package/src/config/commonSchemas.ts +0 -34
- package/src/config/dynamicResolution.ts +0 -49
- package/src/config/index.ts +0 -24
- package/src/config/loadConfig.ts +0 -40
- package/src/config/loadStoreConfig.ts +0 -18
- package/src/config/parseStoreConfig.test-d.ts +0 -40
- package/src/config/parseStoreConfig.ts +0 -317
- package/src/config/validation.ts +0 -163
- package/src/config/world/index.ts +0 -4
- package/src/config/world/loadWorldConfig.test-d.ts +0 -11
- package/src/config/world/loadWorldConfig.ts +0 -26
- package/src/config/world/parseWorldConfig.ts +0 -56
- package/src/config/world/resolveWorldConfig.ts +0 -80
- package/src/config/world/userTypes.ts +0 -74
- package/src/utils/typeUtils.ts +0 -17
|
@@ -1,145 +1,3 @@
|
|
|
1
|
-
// src/config/validation.ts
|
|
2
|
-
import { ethers } from "ethers";
|
|
3
|
-
import { ZodIssueCode } from "zod";
|
|
4
|
-
function validateName(name, ctx) {
|
|
5
|
-
if (!/^\w+$/.test(name)) {
|
|
6
|
-
ctx.addIssue({
|
|
7
|
-
code: ZodIssueCode.custom,
|
|
8
|
-
message: `Name must contain only alphanumeric & underscore characters`
|
|
9
|
-
});
|
|
10
|
-
}
|
|
11
|
-
}
|
|
12
|
-
function validateCapitalizedName(name, ctx) {
|
|
13
|
-
validateName(name, ctx);
|
|
14
|
-
if (!/^[A-Z]/.test(name)) {
|
|
15
|
-
ctx.addIssue({
|
|
16
|
-
code: ZodIssueCode.custom,
|
|
17
|
-
message: `Name must start with a capital letter`
|
|
18
|
-
});
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
function validateUncapitalizedName(name, ctx) {
|
|
22
|
-
validateName(name, ctx);
|
|
23
|
-
if (!/^[a-z]/.test(name)) {
|
|
24
|
-
ctx.addIssue({
|
|
25
|
-
code: ZodIssueCode.custom,
|
|
26
|
-
message: `Name must start with a lowercase letter`
|
|
27
|
-
});
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
function validateEnum(members, ctx) {
|
|
31
|
-
if (members.length === 0) {
|
|
32
|
-
ctx.addIssue({
|
|
33
|
-
code: ZodIssueCode.custom,
|
|
34
|
-
message: `Enum must not be empty`
|
|
35
|
-
});
|
|
36
|
-
}
|
|
37
|
-
if (members.length >= 256) {
|
|
38
|
-
ctx.addIssue({
|
|
39
|
-
code: ZodIssueCode.custom,
|
|
40
|
-
message: `Length of enum must be < 256`
|
|
41
|
-
});
|
|
42
|
-
}
|
|
43
|
-
const duplicates = getDuplicates(members);
|
|
44
|
-
if (duplicates.length > 0) {
|
|
45
|
-
ctx.addIssue({
|
|
46
|
-
code: ZodIssueCode.custom,
|
|
47
|
-
message: `Enum must not have duplicate names for: ${duplicates.join(", ")}`
|
|
48
|
-
});
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
function _factoryForValidateRoute(requireNonEmpty, requireSingleLevel) {
|
|
52
|
-
return (route, ctx) => {
|
|
53
|
-
if (route === "") {
|
|
54
|
-
if (requireNonEmpty) {
|
|
55
|
-
ctx.addIssue({
|
|
56
|
-
code: ZodIssueCode.custom,
|
|
57
|
-
message: `Route must not be empty`
|
|
58
|
-
});
|
|
59
|
-
}
|
|
60
|
-
return;
|
|
61
|
-
}
|
|
62
|
-
if (route[0] !== "/") {
|
|
63
|
-
ctx.addIssue({
|
|
64
|
-
code: ZodIssueCode.custom,
|
|
65
|
-
message: `Route must start with "/"`
|
|
66
|
-
});
|
|
67
|
-
}
|
|
68
|
-
if (route[route.length - 1] === "/") {
|
|
69
|
-
ctx.addIssue({
|
|
70
|
-
code: ZodIssueCode.custom,
|
|
71
|
-
message: `Route must not end with "/"`
|
|
72
|
-
});
|
|
73
|
-
}
|
|
74
|
-
const parts = route.split("/");
|
|
75
|
-
if (requireSingleLevel && parts.length > 2) {
|
|
76
|
-
ctx.addIssue({
|
|
77
|
-
code: ZodIssueCode.custom,
|
|
78
|
-
message: `Route must only have one level (e.g. "/foo")`
|
|
79
|
-
});
|
|
80
|
-
}
|
|
81
|
-
for (let i = 1; i < parts.length; i++) {
|
|
82
|
-
if (parts[i] === "") {
|
|
83
|
-
ctx.addIssue({
|
|
84
|
-
code: ZodIssueCode.custom,
|
|
85
|
-
message: `Route must not contain empty route fragments (e.g. "//")`
|
|
86
|
-
});
|
|
87
|
-
}
|
|
88
|
-
if (!/^\w+$/.test(parts[i])) {
|
|
89
|
-
ctx.addIssue({
|
|
90
|
-
code: ZodIssueCode.custom,
|
|
91
|
-
message: `Route must contain only alphanumeric & underscore characters`
|
|
92
|
-
});
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
};
|
|
96
|
-
}
|
|
97
|
-
var validateRoute = _factoryForValidateRoute(true, false);
|
|
98
|
-
var validateBaseRoute = _factoryForValidateRoute(false, false);
|
|
99
|
-
var validateSingleLevelRoute = _factoryForValidateRoute(true, true);
|
|
100
|
-
function validateEthereumAddress(address, ctx) {
|
|
101
|
-
if (!ethers.utils.isAddress(address)) {
|
|
102
|
-
ctx.addIssue({
|
|
103
|
-
code: ZodIssueCode.custom,
|
|
104
|
-
message: `Address must be a valid Ethereum address`
|
|
105
|
-
});
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
function getDuplicates(array) {
|
|
109
|
-
const checked = /* @__PURE__ */ new Set();
|
|
110
|
-
const duplicates = /* @__PURE__ */ new Set();
|
|
111
|
-
for (const element of array) {
|
|
112
|
-
if (checked.has(element)) {
|
|
113
|
-
duplicates.add(element);
|
|
114
|
-
}
|
|
115
|
-
checked.add(element);
|
|
116
|
-
}
|
|
117
|
-
return [...duplicates];
|
|
118
|
-
}
|
|
119
|
-
function validateSelector(name, ctx) {
|
|
120
|
-
if (name.length > 16) {
|
|
121
|
-
ctx.addIssue({
|
|
122
|
-
code: ZodIssueCode.custom,
|
|
123
|
-
message: `Selector must be <= 16 characters`
|
|
124
|
-
});
|
|
125
|
-
}
|
|
126
|
-
if (!/^\w*$/.test(name)) {
|
|
127
|
-
ctx.addIssue({
|
|
128
|
-
code: ZodIssueCode.custom,
|
|
129
|
-
message: `Selector must contain only alphanumeric & underscore characters`
|
|
130
|
-
});
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
function parseStaticArray(abiType) {
|
|
134
|
-
const matches = abiType.match(/^(\w+)\[(\d+)\]$/);
|
|
135
|
-
if (!matches)
|
|
136
|
-
return null;
|
|
137
|
-
return {
|
|
138
|
-
elementType: matches[1],
|
|
139
|
-
staticLength: Number.parseInt(matches[2])
|
|
140
|
-
};
|
|
141
|
-
}
|
|
142
|
-
|
|
143
1
|
// ../schema-type/src/typescript/SchemaType.ts
|
|
144
2
|
var SchemaType = /* @__PURE__ */ ((SchemaType2) => {
|
|
145
3
|
SchemaType2[SchemaType2["UINT8"] = 0] = "UINT8";
|
|
@@ -707,24 +565,162 @@ var StaticAbiTypes = AbiTypes.filter(
|
|
|
707
565
|
(abiType) => getStaticByteLength(AbiTypeToSchemaType[abiType]) > 0
|
|
708
566
|
);
|
|
709
567
|
|
|
568
|
+
// src/render-solidity/userType.ts
|
|
569
|
+
import { parseStaticArray } from "@latticexyz/config";
|
|
570
|
+
function resolveAbiOrUserType(abiOrUserType, config) {
|
|
571
|
+
if (abiOrUserType in AbiTypeToSchemaType) {
|
|
572
|
+
const schemaType = AbiTypeToSchemaType[abiOrUserType];
|
|
573
|
+
return {
|
|
574
|
+
schemaType,
|
|
575
|
+
renderTableType: getSchemaTypeInfo(schemaType)
|
|
576
|
+
};
|
|
577
|
+
}
|
|
578
|
+
const staticArray = parseStaticArray(abiOrUserType);
|
|
579
|
+
if (staticArray) {
|
|
580
|
+
if (staticArray.elementType in AbiTypeToSchemaType) {
|
|
581
|
+
return getStaticArrayTypeInfo(abiOrUserType, staticArray.elementType, staticArray.staticLength);
|
|
582
|
+
} else {
|
|
583
|
+
throw new Error("Static arrays of user types are not supported");
|
|
584
|
+
}
|
|
585
|
+
}
|
|
586
|
+
return getUserTypeInfo(abiOrUserType, config);
|
|
587
|
+
}
|
|
588
|
+
function importForAbiOrUserType(abiOrUserType, usedInDirectory, config) {
|
|
589
|
+
if (abiOrUserType in AbiTypeToSchemaType) {
|
|
590
|
+
return void 0;
|
|
591
|
+
}
|
|
592
|
+
const staticArray = parseStaticArray(abiOrUserType);
|
|
593
|
+
if (staticArray) {
|
|
594
|
+
return void 0;
|
|
595
|
+
}
|
|
596
|
+
return {
|
|
597
|
+
symbol: abiOrUserType,
|
|
598
|
+
fromPath: config.userTypesPath + ".sol",
|
|
599
|
+
usedInPath: usedInDirectory
|
|
600
|
+
};
|
|
601
|
+
}
|
|
602
|
+
function getSchemaTypeInfo(schemaType) {
|
|
603
|
+
const staticByteLength = getStaticByteLength(schemaType);
|
|
604
|
+
const isDynamic = staticByteLength === 0;
|
|
605
|
+
const typeId = SchemaTypeToAbiType[schemaType];
|
|
606
|
+
return {
|
|
607
|
+
typeId,
|
|
608
|
+
typeWithLocation: isDynamic ? typeId + " memory" : typeId,
|
|
609
|
+
enumName: SchemaType[schemaType],
|
|
610
|
+
staticByteLength,
|
|
611
|
+
isDynamic,
|
|
612
|
+
typeWrap: "",
|
|
613
|
+
typeUnwrap: "",
|
|
614
|
+
internalTypeId: typeId
|
|
615
|
+
};
|
|
616
|
+
}
|
|
617
|
+
function getUserTypeInfo(userType, config) {
|
|
618
|
+
if (userType in config.enums) {
|
|
619
|
+
const schemaType = 0 /* UINT8 */;
|
|
620
|
+
const staticByteLength = getStaticByteLength(schemaType);
|
|
621
|
+
const isDynamic = staticByteLength === 0;
|
|
622
|
+
const typeId = userType;
|
|
623
|
+
return {
|
|
624
|
+
schemaType,
|
|
625
|
+
renderTableType: {
|
|
626
|
+
typeId,
|
|
627
|
+
typeWithLocation: typeId,
|
|
628
|
+
enumName: SchemaType[schemaType],
|
|
629
|
+
staticByteLength,
|
|
630
|
+
isDynamic,
|
|
631
|
+
typeWrap: `${userType}`,
|
|
632
|
+
typeUnwrap: `uint8`,
|
|
633
|
+
internalTypeId: `${SchemaTypeToAbiType[schemaType]}`
|
|
634
|
+
}
|
|
635
|
+
};
|
|
636
|
+
}
|
|
637
|
+
throw new Error(`User type "${userType}" does not exist`);
|
|
638
|
+
}
|
|
639
|
+
function getStaticArrayTypeInfo(abiType, elementType, staticLength) {
|
|
640
|
+
const internalTypeId = elementType + "[]";
|
|
641
|
+
const schemaType = AbiTypeToSchemaType[internalTypeId];
|
|
642
|
+
return {
|
|
643
|
+
schemaType,
|
|
644
|
+
renderTableType: {
|
|
645
|
+
typeId: abiType,
|
|
646
|
+
typeWithLocation: `${abiType} memory`,
|
|
647
|
+
enumName: SchemaType[schemaType],
|
|
648
|
+
staticByteLength: 0,
|
|
649
|
+
isDynamic: true,
|
|
650
|
+
typeWrap: `toStaticArray_${elementType}_${staticLength}`,
|
|
651
|
+
typeUnwrap: `fromStaticArray_${elementType}_${staticLength}`,
|
|
652
|
+
typeWrappingData: {
|
|
653
|
+
kind: "staticArray",
|
|
654
|
+
elementType,
|
|
655
|
+
staticLength
|
|
656
|
+
},
|
|
657
|
+
internalTypeId
|
|
658
|
+
}
|
|
659
|
+
};
|
|
660
|
+
}
|
|
661
|
+
|
|
662
|
+
// src/utils/format.ts
|
|
663
|
+
import chalk from "chalk";
|
|
664
|
+
import prettier from "prettier";
|
|
665
|
+
import prettierPluginSolidity from "prettier-plugin-solidity";
|
|
666
|
+
async function formatSolidity(content, prettierConfigPath) {
|
|
667
|
+
let config;
|
|
668
|
+
if (prettierConfigPath) {
|
|
669
|
+
config = await prettier.resolveConfig(prettierConfigPath);
|
|
670
|
+
}
|
|
671
|
+
try {
|
|
672
|
+
return prettier.format(content, {
|
|
673
|
+
plugins: [prettierPluginSolidity],
|
|
674
|
+
parser: "solidity-parse",
|
|
675
|
+
printWidth: 120,
|
|
676
|
+
semi: true,
|
|
677
|
+
tabWidth: 2,
|
|
678
|
+
useTabs: false,
|
|
679
|
+
bracketSpacing: true,
|
|
680
|
+
...config
|
|
681
|
+
});
|
|
682
|
+
} catch (error) {
|
|
683
|
+
let message;
|
|
684
|
+
if (error instanceof Error) {
|
|
685
|
+
message = error.message;
|
|
686
|
+
} else {
|
|
687
|
+
message = error;
|
|
688
|
+
}
|
|
689
|
+
console.log(chalk.yellow(`Error during output formatting: ${message}`));
|
|
690
|
+
return content;
|
|
691
|
+
}
|
|
692
|
+
}
|
|
693
|
+
async function formatTypescript(content) {
|
|
694
|
+
return prettier.format(content, {
|
|
695
|
+
parser: "typescript"
|
|
696
|
+
});
|
|
697
|
+
}
|
|
698
|
+
|
|
699
|
+
// src/utils/formatAndWrite.ts
|
|
700
|
+
import { mkdirSync, writeFileSync } from "fs";
|
|
701
|
+
import { dirname } from "path";
|
|
702
|
+
async function formatAndWriteSolidity(output, fullOutputPath, logPrefix) {
|
|
703
|
+
const formattedOutput = await formatSolidity(output);
|
|
704
|
+
mkdirSync(dirname(fullOutputPath), { recursive: true });
|
|
705
|
+
writeFileSync(fullOutputPath, formattedOutput);
|
|
706
|
+
console.log(`${logPrefix}: ${fullOutputPath}`);
|
|
707
|
+
}
|
|
708
|
+
async function formatAndWriteTypescript(output, fullOutputPath, logPrefix) {
|
|
709
|
+
const formattedOutput = await formatTypescript(output);
|
|
710
|
+
mkdirSync(dirname(fullOutputPath), { recursive: true });
|
|
711
|
+
writeFileSync(fullOutputPath, formattedOutput);
|
|
712
|
+
console.log(`${logPrefix}: ${fullOutputPath}`);
|
|
713
|
+
}
|
|
714
|
+
|
|
710
715
|
export {
|
|
711
|
-
SchemaType,
|
|
712
|
-
getStaticByteLength,
|
|
713
716
|
encodeSchema,
|
|
714
717
|
SchemaTypeArrayToElement,
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
validateRoute,
|
|
724
|
-
validateBaseRoute,
|
|
725
|
-
validateSingleLevelRoute,
|
|
726
|
-
validateEthereumAddress,
|
|
727
|
-
getDuplicates,
|
|
728
|
-
validateSelector,
|
|
729
|
-
parseStaticArray
|
|
718
|
+
resolveAbiOrUserType,
|
|
719
|
+
importForAbiOrUserType,
|
|
720
|
+
getSchemaTypeInfo,
|
|
721
|
+
getUserTypeInfo,
|
|
722
|
+
formatSolidity,
|
|
723
|
+
formatTypescript,
|
|
724
|
+
formatAndWriteSolidity,
|
|
725
|
+
formatAndWriteTypescript
|
|
730
726
|
};
|
|
@@ -0,0 +1,353 @@
|
|
|
1
|
+
import {
|
|
2
|
+
getOutDirectory,
|
|
3
|
+
getSrcDirectory
|
|
4
|
+
} from "./chunk-FPG73MVN.js";
|
|
5
|
+
|
|
6
|
+
// src/utils/deprecated/exec.ts
|
|
7
|
+
import { execa } from "execa";
|
|
8
|
+
function execLog(command, options) {
|
|
9
|
+
console.log("Cmd:");
|
|
10
|
+
console.log([command, ...options].join(" "));
|
|
11
|
+
return execa(command, options, {
|
|
12
|
+
stdio: ["inherit", "inherit", "inherit"]
|
|
13
|
+
});
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
// src/utils/deprecated/ids.ts
|
|
17
|
+
import { keccak256 as keccak256Bytes, toUtf8Bytes } from "ethers/lib/utils.js";
|
|
18
|
+
import { readFileSync } from "fs";
|
|
19
|
+
var IDregex = new RegExp(/(?<=uint256 constant ID = uint256\(keccak256\(")(.*)(?="\))/);
|
|
20
|
+
function extractIdFromFile(path5) {
|
|
21
|
+
const content = readFileSync(path5).toString();
|
|
22
|
+
const regexResult = IDregex.exec(content);
|
|
23
|
+
return regexResult && regexResult[0];
|
|
24
|
+
}
|
|
25
|
+
function keccak256(data) {
|
|
26
|
+
return keccak256Bytes(toUtf8Bytes(data));
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// src/utils/deprecated/codegen.ts
|
|
30
|
+
import { readFile, writeFile } from "fs/promises";
|
|
31
|
+
import ejs from "ejs";
|
|
32
|
+
import path from "path";
|
|
33
|
+
var contractsDirectory = new URL("../src/contracts", import.meta.url).pathname;
|
|
34
|
+
var stubLibDeploy = readFile(path.join(contractsDirectory, "LibDeployStub.sol"));
|
|
35
|
+
async function generateLibDeploy(configPath, out, systems) {
|
|
36
|
+
const config = JSON.parse(await readFile(configPath, { encoding: "utf8" }));
|
|
37
|
+
config.initializers ??= [];
|
|
38
|
+
if (systems) {
|
|
39
|
+
const systemsArray = Array.isArray(systems) ? systems : [systems];
|
|
40
|
+
config.systems = config.systems.filter((system) => systemsArray.includes(system.name));
|
|
41
|
+
}
|
|
42
|
+
console.log(`Deploy config:
|
|
43
|
+
`, JSON.stringify(config, null, 2));
|
|
44
|
+
console.log("Generating deployment script");
|
|
45
|
+
const LibDeploy = await ejs.renderFile(path.join(contractsDirectory, "LibDeploy.ejs"), config, { async: true });
|
|
46
|
+
const libDeployPath = path.join(out, "LibDeploy.sol");
|
|
47
|
+
await writeFile(libDeployPath, LibDeploy);
|
|
48
|
+
return libDeployPath;
|
|
49
|
+
}
|
|
50
|
+
async function resetLibDeploy(out) {
|
|
51
|
+
await writeFile(path.join(out, "LibDeploy.sol"), await stubLibDeploy);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// src/utils/deprecated/deploy.ts
|
|
55
|
+
import { constants, Wallet } from "ethers";
|
|
56
|
+
|
|
57
|
+
// src/utils/deprecated/findLog.ts
|
|
58
|
+
function findLog(deployLogLines, log) {
|
|
59
|
+
for (const logLine of deployLogLines) {
|
|
60
|
+
if (logLine.includes(log)) {
|
|
61
|
+
return logLine.split(log)[1].trim();
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
throw new Error("Can not find log");
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// src/utils/deprecated/typegen.ts
|
|
68
|
+
import { runTypeChain, glob as typechainGlob } from "typechain";
|
|
69
|
+
import glob from "glob";
|
|
70
|
+
import { rmSync as rmSync2, writeFileSync } from "fs";
|
|
71
|
+
import path3 from "path";
|
|
72
|
+
|
|
73
|
+
// src/utils/deprecated/build.ts
|
|
74
|
+
import { execa as execa2 } from "execa";
|
|
75
|
+
import { copyFileSync, mkdirSync, readdirSync, rmSync } from "fs";
|
|
76
|
+
import path2 from "path";
|
|
77
|
+
async function forgeBuild(options) {
|
|
78
|
+
if (options?.clear) {
|
|
79
|
+
const out = await getOutDirectory();
|
|
80
|
+
console.log("Clearing forge build output directory", out);
|
|
81
|
+
rmSync(out, { recursive: true, force: true });
|
|
82
|
+
}
|
|
83
|
+
console.log("Running forge build");
|
|
84
|
+
const child = execa2("forge", ["build"], {
|
|
85
|
+
stdio: ["inherit", "pipe", "inherit"]
|
|
86
|
+
});
|
|
87
|
+
return (await child).stdout;
|
|
88
|
+
}
|
|
89
|
+
function getContractsInDirectory(dir, exclude) {
|
|
90
|
+
return readdirSync(dir).filter((item) => item.includes(".sol")).map((item) => item.replace(".sol", "")).filter((item) => !exclude?.includes(item));
|
|
91
|
+
}
|
|
92
|
+
function copyAbi(inDir, outDir, contract) {
|
|
93
|
+
try {
|
|
94
|
+
return copyFileSync(path2.join(inDir, contract + ".sol", contract + ".json"), path2.join(outDir, contract + ".json"));
|
|
95
|
+
} catch (e) {
|
|
96
|
+
console.log("Skipping", contract);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
function filterAbi(abiIn = "./out", abiOut = "./abi", exclude = ["Component", "IComponent"]) {
|
|
100
|
+
console.log(`Cleaning output directory (${abiOut}})`);
|
|
101
|
+
rmSync(abiOut, { recursive: true, force: true });
|
|
102
|
+
mkdirSync(abiOut);
|
|
103
|
+
const include = ["Component", "System", "World", "LibQuery"];
|
|
104
|
+
const contracts = getContractsInDirectory(abiIn, exclude).filter((item) => include.find((i) => item.includes(i)));
|
|
105
|
+
console.log("Selected ABIs: ", contracts);
|
|
106
|
+
for (const contract of contracts) {
|
|
107
|
+
if (contract.includes(".t"))
|
|
108
|
+
continue;
|
|
109
|
+
copyAbi(abiIn, abiOut, contract);
|
|
110
|
+
}
|
|
111
|
+
console.log("Successfully moved selected ABIs to ./abi");
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
// src/utils/deprecated/constants.ts
|
|
115
|
+
var systemsDir = "systems";
|
|
116
|
+
var componentsDir = "components";
|
|
117
|
+
|
|
118
|
+
// src/utils/deprecated/typegen.ts
|
|
119
|
+
async function generateAbiTypes(inputDir, outputDir, options) {
|
|
120
|
+
if (options?.clear) {
|
|
121
|
+
console.log("Clearing typechain output directory", outputDir);
|
|
122
|
+
rmSync2(outputDir, { recursive: true, force: true });
|
|
123
|
+
}
|
|
124
|
+
const cwd = options?.cwd ?? process.cwd();
|
|
125
|
+
const allFiles = typechainGlob(cwd, [`${inputDir}/**/+([a-zA-Z0-9_]).json`]);
|
|
126
|
+
const result = await runTypeChain({
|
|
127
|
+
cwd,
|
|
128
|
+
filesToProcess: allFiles,
|
|
129
|
+
allFiles,
|
|
130
|
+
outDir: outputDir,
|
|
131
|
+
target: "ethers-v5"
|
|
132
|
+
});
|
|
133
|
+
console.log(`Successfully generated ${result.filesGenerated} files`);
|
|
134
|
+
}
|
|
135
|
+
async function generateSystemTypes(outputDir, options) {
|
|
136
|
+
if (options?.clear) {
|
|
137
|
+
console.log("Clearing system type output files", outputDir);
|
|
138
|
+
rmSync2(path3.join(outputDir, "/SystemTypes.ts"), { force: true });
|
|
139
|
+
rmSync2(path3.join(outputDir, "/SystemAbis.mts"), { force: true });
|
|
140
|
+
rmSync2(path3.join(outputDir, "/SystemAbis.mjs"), { force: true });
|
|
141
|
+
rmSync2(path3.join(outputDir, "/SystemMappings.ts"), { force: true });
|
|
142
|
+
}
|
|
143
|
+
let abis = [];
|
|
144
|
+
let systems = [];
|
|
145
|
+
let ids = [];
|
|
146
|
+
let typePaths = [];
|
|
147
|
+
const srcDir = await getSrcDirectory();
|
|
148
|
+
const systemsPath = path3.join(srcDir, systemsDir, "*.sol");
|
|
149
|
+
const matches = glob.sync(systemsPath);
|
|
150
|
+
systems = matches.map((path5) => {
|
|
151
|
+
const fragments = path5.split("/");
|
|
152
|
+
return fragments[fragments.length - 1].split(".sol")[0];
|
|
153
|
+
});
|
|
154
|
+
ids = matches.map((path5, index) => {
|
|
155
|
+
const id = extractIdFromFile(path5);
|
|
156
|
+
if (!id) {
|
|
157
|
+
console.log("Path:", path5);
|
|
158
|
+
console.log("ID:", id);
|
|
159
|
+
throw new Error(
|
|
160
|
+
"No ID found for" + matches[index] + ". Make sure your system source file includes a ID definition (uint256 constant ID = uint256(keccak256(<ID>));)"
|
|
161
|
+
);
|
|
162
|
+
}
|
|
163
|
+
return id;
|
|
164
|
+
});
|
|
165
|
+
abis = systems.map((system) => `../abi/${system}.json`);
|
|
166
|
+
typePaths = systems.map((system) => `./ethers-contracts/${system}.ts`);
|
|
167
|
+
console.log("Matches", systems);
|
|
168
|
+
console.log("Solidity", ids);
|
|
169
|
+
console.log("Type paths", typePaths);
|
|
170
|
+
console.log("ABIs", abis);
|
|
171
|
+
const SystemMappings = `// Autogenerated using mud system-types
|
|
172
|
+
export const systemToId = {
|
|
173
|
+
${systems.map((system, index) => ` ${system}: "${ids[index]}",`).join("\n")}
|
|
174
|
+
};
|
|
175
|
+
|
|
176
|
+
export const idToSystem = {
|
|
177
|
+
${ids.map((id, index) => ` "${id}": "${systems[index]}",`).join("\n")}
|
|
178
|
+
};
|
|
179
|
+
`;
|
|
180
|
+
const SystemTypes = `// Autogenerated using mud system-types
|
|
181
|
+
${typePaths.map((path5, index) => `import { ${systems[index]} } from "${path5.replace(".ts", "")}";`).join("\n")}
|
|
182
|
+
|
|
183
|
+
export type SystemTypes = {
|
|
184
|
+
${systems.map((system, index) => ` "${ids[index]}": ${system};`).join("\n")}
|
|
185
|
+
};
|
|
186
|
+
`;
|
|
187
|
+
const SystemAbis = `// Autogenerated using mud system-types
|
|
188
|
+
${abis.map((path5, index) => `import ${systems[index]} from "${path5}";`).join("\n")}
|
|
189
|
+
|
|
190
|
+
export const SystemAbis = {
|
|
191
|
+
${systems.map((system, index) => ` "${ids[index]}": ${system}.abi,`).join("\n")}
|
|
192
|
+
};
|
|
193
|
+
`;
|
|
194
|
+
console.log("Generating files:");
|
|
195
|
+
console.log("SystemTypes.ts", SystemTypes);
|
|
196
|
+
console.log("SystemAbis.mts", SystemAbis);
|
|
197
|
+
console.log("SystemMappings.ts", SystemMappings);
|
|
198
|
+
writeFileSync(`${outputDir}/SystemTypes.ts`, SystemTypes);
|
|
199
|
+
writeFileSync(`${outputDir}/SystemAbis.mts`, SystemAbis);
|
|
200
|
+
writeFileSync(`${outputDir}/SystemAbis.mjs`, SystemAbis);
|
|
201
|
+
writeFileSync(`${outputDir}/SystemMappings.ts`, SystemMappings);
|
|
202
|
+
}
|
|
203
|
+
async function generateTypes(abiDir, outputDir = "./types", options) {
|
|
204
|
+
if (!abiDir) {
|
|
205
|
+
console.log("Compiling contracts");
|
|
206
|
+
const buildOutput = await getOutDirectory();
|
|
207
|
+
abiDir = "./abi";
|
|
208
|
+
await forgeBuild(options);
|
|
209
|
+
filterAbi(buildOutput, abiDir);
|
|
210
|
+
}
|
|
211
|
+
await generateAbiTypes(abiDir, path3.join(outputDir, "ethers-contracts"), options);
|
|
212
|
+
await generateSystemTypes(outputDir, options);
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
// src/utils/deprecated/deploy.ts
|
|
216
|
+
import { execa as execa3 } from "execa";
|
|
217
|
+
import { StaticJsonRpcProvider } from "@ethersproject/providers";
|
|
218
|
+
import path4 from "path";
|
|
219
|
+
var contractsDirectory2 = new URL("../src/contracts", import.meta.url).pathname;
|
|
220
|
+
async function deploy(deployerPrivateKey, rpc = "http://localhost:8545", worldAddress, reuseComponents, gasPrice) {
|
|
221
|
+
const address = deployerPrivateKey ? new Wallet(deployerPrivateKey).address : constants.AddressZero;
|
|
222
|
+
if (gasPrice == null) {
|
|
223
|
+
try {
|
|
224
|
+
console.log("Fetching gas price...");
|
|
225
|
+
const provider = new StaticJsonRpcProvider(rpc, { name: "AnyNetwork", chainId: 1234 });
|
|
226
|
+
gasPrice = (await provider.getGasPrice()).toNumber() * 1.3;
|
|
227
|
+
console.log("Gas price:", gasPrice);
|
|
228
|
+
} catch (e) {
|
|
229
|
+
console.log("Could not fetch gas price");
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
const child = execa3(
|
|
233
|
+
"forge",
|
|
234
|
+
[
|
|
235
|
+
"script",
|
|
236
|
+
path4.join(contractsDirectory2, "/Deploy.sol"),
|
|
237
|
+
"--target-contract",
|
|
238
|
+
"Deploy",
|
|
239
|
+
"-vvv",
|
|
240
|
+
...!deployerPrivateKey ? [] : ["--broadcast", "--private-keys", deployerPrivateKey],
|
|
241
|
+
"--sig",
|
|
242
|
+
"broadcastDeploy(address,address,bool)",
|
|
243
|
+
address,
|
|
244
|
+
// Deployer
|
|
245
|
+
worldAddress || constants.AddressZero,
|
|
246
|
+
// World address (0 = deploy a new world)
|
|
247
|
+
reuseComponents ? "true" : "false",
|
|
248
|
+
// Reuse components?
|
|
249
|
+
"--fork-url",
|
|
250
|
+
rpc,
|
|
251
|
+
...gasPrice != null ? ["--with-gas-price", String(Math.round(gasPrice))] : []
|
|
252
|
+
],
|
|
253
|
+
{ stdio: ["inherit", "pipe", "pipe"] }
|
|
254
|
+
);
|
|
255
|
+
child.stderr?.on("data", (data) => console.log("stderr:", data.toString()));
|
|
256
|
+
child.stdout?.on("data", (data) => console.log(data.toString()));
|
|
257
|
+
const lines = (await child).stdout?.split("\n");
|
|
258
|
+
const deployedWorldAddress = findLog(lines, "world: address");
|
|
259
|
+
const initialBlockNumber = findLog(lines, "initialBlockNumber: uint256");
|
|
260
|
+
return { child: await child, deployedWorldAddress, initialBlockNumber };
|
|
261
|
+
}
|
|
262
|
+
async function generateAndDeploy(args) {
|
|
263
|
+
let libDeployPath;
|
|
264
|
+
let deployedWorldAddress;
|
|
265
|
+
let initialBlockNumber;
|
|
266
|
+
try {
|
|
267
|
+
libDeployPath = await generateLibDeploy(args.config, contractsDirectory2, args.systems);
|
|
268
|
+
await generateTypes(void 0, "./types", { clear: args.clear });
|
|
269
|
+
const result = await deploy(
|
|
270
|
+
args.deployerPrivateKey,
|
|
271
|
+
args.rpc,
|
|
272
|
+
args.worldAddress,
|
|
273
|
+
Boolean(args.reuseComponents),
|
|
274
|
+
args.gasPrice
|
|
275
|
+
);
|
|
276
|
+
deployedWorldAddress = result.deployedWorldAddress;
|
|
277
|
+
initialBlockNumber = result.initialBlockNumber;
|
|
278
|
+
} finally {
|
|
279
|
+
console.log("Cleaning up deployment script");
|
|
280
|
+
if (libDeployPath)
|
|
281
|
+
await resetLibDeploy(contractsDirectory2);
|
|
282
|
+
}
|
|
283
|
+
return { deployedWorldAddress, initialBlockNumber };
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
// src/utils/deprecated/hsr.ts
|
|
287
|
+
import chokidar from "chokidar";
|
|
288
|
+
import { readFileSync as readFileSync2 } from "fs";
|
|
289
|
+
var ImportsRegex = new RegExp(/(?<=import ").*(?=";)|(?<=from ").*(?=";)/g);
|
|
290
|
+
function extractImports(path5) {
|
|
291
|
+
const content = readFileSync2(path5).toString();
|
|
292
|
+
const regexResult = [...content.matchAll(ImportsRegex)].map((match) => match[0]).map((path6) => path6.split("/").at(-1));
|
|
293
|
+
return regexResult;
|
|
294
|
+
}
|
|
295
|
+
function findDependencies(file, dependencyGraph, visited = []) {
|
|
296
|
+
const dependencies = dependencyGraph[file] ?? [];
|
|
297
|
+
const subDependencies = dependencies.flatMap((d) => {
|
|
298
|
+
if (visited.includes(d)) {
|
|
299
|
+
console.warn("Circular dependency detected: ", d, dependencyGraph[d]);
|
|
300
|
+
return [];
|
|
301
|
+
}
|
|
302
|
+
return findDependencies(d, dependencyGraph, [...visited, d]);
|
|
303
|
+
});
|
|
304
|
+
return [.../* @__PURE__ */ new Set([...dependencies, ...subDependencies])];
|
|
305
|
+
}
|
|
306
|
+
function hsr(root, replaceSystems) {
|
|
307
|
+
const dependencyGraph = {};
|
|
308
|
+
const systems = /* @__PURE__ */ new Set();
|
|
309
|
+
console.log("Watching system file changes...");
|
|
310
|
+
chokidar.watch(root).on("all", async (event, path5) => {
|
|
311
|
+
console.log(`[${event}]: ${path5}`);
|
|
312
|
+
const changedFile = path5.split("/").at(-1);
|
|
313
|
+
if (["add", "change"].includes(event)) {
|
|
314
|
+
const imports = extractImports(path5);
|
|
315
|
+
for (const importedFile of imports) {
|
|
316
|
+
dependencyGraph[importedFile] ??= [];
|
|
317
|
+
dependencyGraph[importedFile].push(changedFile);
|
|
318
|
+
}
|
|
319
|
+
if (path5.includes("systems") && path5.includes(".sol"))
|
|
320
|
+
systems.add(changedFile);
|
|
321
|
+
}
|
|
322
|
+
if (event === "change") {
|
|
323
|
+
const dependencies = findDependencies(changedFile, dependencyGraph);
|
|
324
|
+
const changedSystems = [
|
|
325
|
+
...new Set([changedFile, ...dependencies].filter((f) => systems.has(f)).map((f) => f.replace(".sol", "")))
|
|
326
|
+
];
|
|
327
|
+
console.log("Systems to replace", changedSystems);
|
|
328
|
+
if (changedSystems.length > 0)
|
|
329
|
+
await replaceSystems(changedSystems);
|
|
330
|
+
console.log("Watching system file changes...");
|
|
331
|
+
}
|
|
332
|
+
});
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
export {
|
|
336
|
+
execLog,
|
|
337
|
+
IDregex,
|
|
338
|
+
extractIdFromFile,
|
|
339
|
+
keccak256,
|
|
340
|
+
generateLibDeploy,
|
|
341
|
+
resetLibDeploy,
|
|
342
|
+
findLog,
|
|
343
|
+
forgeBuild,
|
|
344
|
+
filterAbi,
|
|
345
|
+
systemsDir,
|
|
346
|
+
componentsDir,
|
|
347
|
+
generateAbiTypes,
|
|
348
|
+
generateSystemTypes,
|
|
349
|
+
generateTypes,
|
|
350
|
+
deploy,
|
|
351
|
+
generateAndDeploy,
|
|
352
|
+
hsr
|
|
353
|
+
};
|