@latticexyz/cli 1.41.0 → 2.0.0-alpha.0
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-GR245KYP.js → chunk-J4DJQNIC.js} +679 -133
- package/dist/chunk-O57QENJ6.js +23039 -0
- package/dist/config/index.d.ts +606 -292
- package/dist/config/index.js +49 -26
- package/dist/index.d.ts +2 -110
- package/dist/index.js +9 -50
- package/dist/mud.js +937 -57
- package/dist/utils/index.d.ts +92 -4
- package/dist/utils/index.js +2 -3
- package/package.json +10 -9
- package/src/commands/deploy-v2.ts +11 -15
- package/src/commands/index.ts +2 -0
- package/src/commands/worldgen.ts +55 -0
- package/src/config/commonSchemas.ts +11 -13
- package/src/config/dynamicResolution.ts +49 -0
- package/src/config/index.ts +15 -3
- package/src/config/loadStoreConfig.ts +1 -1
- package/src/config/parseStoreConfig.test-d.ts +31 -5
- package/src/config/parseStoreConfig.ts +218 -78
- package/src/config/validation.ts +25 -0
- package/src/config/world/index.ts +4 -0
- package/src/config/{loadWorldConfig.test-d.ts → world/loadWorldConfig.test-d.ts} +3 -3
- package/src/config/world/loadWorldConfig.ts +26 -0
- package/src/config/world/parseWorldConfig.ts +55 -0
- package/src/config/world/resolveWorldConfig.ts +80 -0
- package/src/config/world/userTypes.ts +72 -0
- package/src/index.ts +4 -6
- package/src/render-solidity/common.ts +51 -6
- package/src/render-solidity/field.ts +40 -44
- package/src/render-solidity/index.ts +5 -1
- package/src/render-solidity/record.ts +56 -73
- package/src/render-solidity/renderSystemInterface.ts +31 -0
- package/src/render-solidity/renderTable.ts +98 -70
- package/src/render-solidity/renderTypeHelpers.ts +99 -0
- package/src/render-solidity/renderTypesFromConfig.ts +2 -2
- package/src/render-solidity/renderWorld.ts +24 -0
- package/src/render-solidity/{renderTablesFromConfig.ts → tableOptions.ts} +28 -30
- package/src/render-solidity/tablegen.ts +20 -22
- package/src/render-solidity/types.ts +39 -5
- package/src/render-solidity/userType.ts +80 -48
- package/src/render-solidity/worldgen.ts +60 -0
- package/src/utils/contractToInterface.ts +130 -0
- package/src/utils/deploy-v2.ts +268 -101
- package/src/utils/formatAndWrite.ts +12 -0
- package/src/utils/getChainId.ts +10 -0
- package/src/utils/typeUtils.ts +17 -0
- package/dist/chunk-AER7UDD4.js +0 -0
- package/dist/chunk-XRS7KWBZ.js +0 -547
- package/dist/chunk-YZATC2M3.js +0 -397
- package/dist/chunk-ZYDMYSTH.js +0 -1178
- package/dist/deploy-v2-b7b3207d.d.ts +0 -92
- package/src/config/loadWorldConfig.ts +0 -178
- package/src/constants.ts +0 -1
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { AbiType, StaticAbiType } from "@latticexyz/schema-type";
|
|
2
|
+
|
|
3
|
+
export type RequireKeys<T extends Record<string, unknown>, P extends string> = T & Required<Pick<T, P>>;
|
|
4
|
+
|
|
5
|
+
// This allows unions between string literals and `string` without sacrificing autocompletion.
|
|
6
|
+
// Workaround for https://github.com/Microsoft/TypeScript/issues/29729
|
|
7
|
+
export type StringForUnion = string & Record<never, never>;
|
|
8
|
+
|
|
9
|
+
export type StaticArray = `${StaticAbiType}[${number}]`;
|
|
10
|
+
// static arrays and inferred enum names get mixed together - this helper separates them
|
|
11
|
+
export type ExtractUserTypes<UnknownTypes extends StringForUnion> = Exclude<UnknownTypes, AbiType | StaticArray>;
|
|
12
|
+
|
|
13
|
+
// When type inference sees multiple uses of 1 generic, it can only guess
|
|
14
|
+
// which of those are supposed to define the generic (and it will be wrong in complex situations).
|
|
15
|
+
// This helper explicitly makes a type that's dependent on some generic,
|
|
16
|
+
// and will not be inferred as the generic's definition.
|
|
17
|
+
export type AsDependent<T> = T extends infer P ? P : never;
|
package/dist/chunk-AER7UDD4.js
DELETED
|
File without changes
|
package/dist/chunk-XRS7KWBZ.js
DELETED
|
@@ -1,547 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
getSchemaTypeInfo,
|
|
3
|
-
resolveSchemaOrUserType
|
|
4
|
-
} from "./chunk-ZYDMYSTH.js";
|
|
5
|
-
import {
|
|
6
|
-
SchemaTypeArrayToElement
|
|
7
|
-
} from "./chunk-GR245KYP.js";
|
|
8
|
-
|
|
9
|
-
// src/render-solidity/common.ts
|
|
10
|
-
var renderedSolidityHeader = `// SPDX-License-Identifier: MIT
|
|
11
|
-
pragma solidity >=0.8.0;
|
|
12
|
-
|
|
13
|
-
/* Autogenerated file. Do not edit manually. */`;
|
|
14
|
-
function renderList(list, renderItem) {
|
|
15
|
-
return internalRenderList("", list, renderItem);
|
|
16
|
-
}
|
|
17
|
-
function renderArguments(args) {
|
|
18
|
-
const filteredArgs = args.filter((arg) => arg !== void 0 && arg !== "");
|
|
19
|
-
return internalRenderList(",", filteredArgs, (arg) => arg);
|
|
20
|
-
}
|
|
21
|
-
function renderCommonData({ staticRouteData, primaryKeys }) {
|
|
22
|
-
const _tableId = staticRouteData ? "" : "_tableId";
|
|
23
|
-
const _typedTableId = staticRouteData ? "" : "uint256 _tableId";
|
|
24
|
-
const _keyArgs = renderArguments(primaryKeys.map(({ name }) => name));
|
|
25
|
-
const _typedKeyArgs = renderArguments(primaryKeys.map(({ name, typeWithLocation }) => `${typeWithLocation} ${name}`));
|
|
26
|
-
const _primaryKeysDefinition = `
|
|
27
|
-
bytes32[] memory _primaryKeys = new bytes32[](${primaryKeys.length});
|
|
28
|
-
${renderList(
|
|
29
|
-
primaryKeys,
|
|
30
|
-
(primaryKey, index) => `_primaryKeys[${index}] = ${renderValueTypeToBytes32(primaryKey.name, primaryKey)};`
|
|
31
|
-
)}
|
|
32
|
-
`;
|
|
33
|
-
return {
|
|
34
|
-
_tableId,
|
|
35
|
-
_typedTableId,
|
|
36
|
-
_keyArgs,
|
|
37
|
-
_typedKeyArgs,
|
|
38
|
-
_primaryKeysDefinition
|
|
39
|
-
};
|
|
40
|
-
}
|
|
41
|
-
function renderImports(imports) {
|
|
42
|
-
const aggregatedImports = /* @__PURE__ */ new Map();
|
|
43
|
-
for (const { symbol, path: path2 } of imports) {
|
|
44
|
-
if (!aggregatedImports.has(path2)) {
|
|
45
|
-
aggregatedImports.set(path2, /* @__PURE__ */ new Set());
|
|
46
|
-
}
|
|
47
|
-
aggregatedImports.get(path2)?.add(symbol);
|
|
48
|
-
}
|
|
49
|
-
const renderedImports = [];
|
|
50
|
-
for (const [path2, symbols] of aggregatedImports) {
|
|
51
|
-
const renderedSymbols = [...symbols].join(", ");
|
|
52
|
-
renderedImports.push(`import { ${renderedSymbols} } from "${path2}";`);
|
|
53
|
-
}
|
|
54
|
-
return renderedImports.join("\n");
|
|
55
|
-
}
|
|
56
|
-
function renderValueTypeToBytes32(name, { staticByteLength, typeUnwrap, internalTypeId }) {
|
|
57
|
-
const bits = staticByteLength * 8;
|
|
58
|
-
const innerText = `${typeUnwrap}(${name})`;
|
|
59
|
-
if (internalTypeId.match(/^uint\d{1,3}$/)) {
|
|
60
|
-
return `bytes32(uint256(${innerText}))`;
|
|
61
|
-
} else if (internalTypeId.match(/^int\d{1,3}$/)) {
|
|
62
|
-
return `bytes32(uint256(uint${bits}(${innerText})))`;
|
|
63
|
-
} else if (internalTypeId.match(/^bytes\d{1,2}$/)) {
|
|
64
|
-
return `bytes32(${innerText})`;
|
|
65
|
-
} else if (internalTypeId === "address") {
|
|
66
|
-
return `bytes32(bytes20(${innerText}))`;
|
|
67
|
-
} else if (internalTypeId === "bool") {
|
|
68
|
-
return `_boolToBytes32(${innerText})`;
|
|
69
|
-
} else {
|
|
70
|
-
throw new Error(`Unknown value type id ${internalTypeId}`);
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
function internalRenderList(lineTerminator, list, renderItem) {
|
|
74
|
-
return list.map((item, index) => renderItem(item, index) + (index === list.length - 1 ? "" : lineTerminator)).join("\n");
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
// src/render-solidity/field.ts
|
|
78
|
-
function renderFieldMethods(options) {
|
|
79
|
-
const { _typedTableId, _typedKeyArgs, _primaryKeysDefinition } = renderCommonData(options);
|
|
80
|
-
let result = "";
|
|
81
|
-
for (const [index, field] of options.fields.entries()) {
|
|
82
|
-
const _typedFieldName = `${field.typeWithLocation} ${field.name}`;
|
|
83
|
-
result += `
|
|
84
|
-
/** Get ${field.name} */
|
|
85
|
-
function get${field.methodNameSuffix}(${renderArguments([
|
|
86
|
-
_typedTableId,
|
|
87
|
-
_typedKeyArgs
|
|
88
|
-
])}) internal view returns (${_typedFieldName}) {
|
|
89
|
-
${_primaryKeysDefinition}
|
|
90
|
-
bytes memory _blob = StoreSwitch.getField(_tableId, _primaryKeys, ${index});
|
|
91
|
-
return ${renderDecodeFieldSingle(field)};
|
|
92
|
-
}
|
|
93
|
-
`;
|
|
94
|
-
if (options.storeArgument) {
|
|
95
|
-
result += `
|
|
96
|
-
/** Get ${field.name} from the specified store */
|
|
97
|
-
function get${field.methodNameSuffix}(${renderArguments([
|
|
98
|
-
_typedTableId,
|
|
99
|
-
`IStore _store`,
|
|
100
|
-
_typedKeyArgs
|
|
101
|
-
])}) internal view returns (${_typedFieldName}) {
|
|
102
|
-
${_primaryKeysDefinition}
|
|
103
|
-
bytes memory _blob = _store.getField(_tableId, _primaryKeys, ${index});
|
|
104
|
-
return ${renderDecodeFieldSingle(field)};
|
|
105
|
-
}
|
|
106
|
-
`;
|
|
107
|
-
}
|
|
108
|
-
result += `
|
|
109
|
-
/** Set ${field.name} */
|
|
110
|
-
function set${field.methodNameSuffix}(${renderArguments([
|
|
111
|
-
_typedTableId,
|
|
112
|
-
_typedKeyArgs,
|
|
113
|
-
_typedFieldName
|
|
114
|
-
])}) internal {
|
|
115
|
-
${_primaryKeysDefinition}
|
|
116
|
-
StoreSwitch.setField(_tableId, _primaryKeys, ${index}, ${renderEncodeField(field)});
|
|
117
|
-
}
|
|
118
|
-
`;
|
|
119
|
-
if (field.isDynamic) {
|
|
120
|
-
const portionData = fieldPortionData(field);
|
|
121
|
-
result += `
|
|
122
|
-
/** Push ${portionData.title} to ${field.name} */
|
|
123
|
-
function push${field.methodNameSuffix}(${renderArguments([
|
|
124
|
-
_typedTableId,
|
|
125
|
-
_typedKeyArgs,
|
|
126
|
-
`${portionData.typeWithLocation} ${portionData.name}`
|
|
127
|
-
])}) internal {
|
|
128
|
-
${_primaryKeysDefinition}
|
|
129
|
-
bytes memory _blob = StoreSwitch.getField(_tableId, _primaryKeys, ${index});
|
|
130
|
-
bytes memory _newBlob = abi.encodePacked(_blob, ${portionData.encoded});
|
|
131
|
-
StoreSwitch.setField(_tableId, _primaryKeys, ${index}, _newBlob);
|
|
132
|
-
}
|
|
133
|
-
`;
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
return result;
|
|
137
|
-
}
|
|
138
|
-
function renderEncodeField(field) {
|
|
139
|
-
let func;
|
|
140
|
-
if (field.arrayElement) {
|
|
141
|
-
func = "EncodeArray.encode";
|
|
142
|
-
} else if (field.isDynamic) {
|
|
143
|
-
func = "bytes";
|
|
144
|
-
} else {
|
|
145
|
-
func = "abi.encodePacked";
|
|
146
|
-
}
|
|
147
|
-
return `${func}(${field.typeUnwrap}(${field.name}))`;
|
|
148
|
-
}
|
|
149
|
-
function renderDecodeValueType(field, offset) {
|
|
150
|
-
const { staticByteLength, internalTypeId } = field;
|
|
151
|
-
const innerSlice = `Bytes.slice${staticByteLength}(_blob, ${offset})`;
|
|
152
|
-
const bits = staticByteLength * 8;
|
|
153
|
-
let result;
|
|
154
|
-
if (internalTypeId.match(/^uint\d{1,3}$/) || internalTypeId === "address") {
|
|
155
|
-
result = `${internalTypeId}(${innerSlice})`;
|
|
156
|
-
} else if (internalTypeId.match(/^int\d{1,3}$/)) {
|
|
157
|
-
result = `${internalTypeId}(uint${bits}(${innerSlice}))`;
|
|
158
|
-
} else if (internalTypeId.match(/^bytes\d{1,2}$/)) {
|
|
159
|
-
result = innerSlice;
|
|
160
|
-
} else if (internalTypeId === "bool") {
|
|
161
|
-
result = `_toBool(uint8(${innerSlice}))`;
|
|
162
|
-
} else {
|
|
163
|
-
throw new Error(`Unknown value type id ${internalTypeId}`);
|
|
164
|
-
}
|
|
165
|
-
return `${field.typeWrap}(${result})`;
|
|
166
|
-
}
|
|
167
|
-
function fieldPortionData(field) {
|
|
168
|
-
const methodNameSuffix = "";
|
|
169
|
-
if (field.arrayElement) {
|
|
170
|
-
const name = "_element";
|
|
171
|
-
return {
|
|
172
|
-
typeWithLocation: field.arrayElement.typeWithLocation,
|
|
173
|
-
name: "_element",
|
|
174
|
-
encoded: renderEncodeField({ ...field.arrayElement, arrayElement: void 0, name, methodNameSuffix }),
|
|
175
|
-
title: "an element"
|
|
176
|
-
};
|
|
177
|
-
} else {
|
|
178
|
-
const name = "_slice";
|
|
179
|
-
return {
|
|
180
|
-
typeWithLocation: `${field.typeId} memory`,
|
|
181
|
-
name,
|
|
182
|
-
encoded: renderEncodeField({ ...field, name, methodNameSuffix }),
|
|
183
|
-
title: "a slice"
|
|
184
|
-
};
|
|
185
|
-
}
|
|
186
|
-
}
|
|
187
|
-
function renderDecodeFieldSingle(field) {
|
|
188
|
-
const { isDynamic, arrayElement } = field;
|
|
189
|
-
if (arrayElement) {
|
|
190
|
-
return `${field.typeWrap}(
|
|
191
|
-
SliceLib.getSubslice(_blob, 0, _blob.length).decodeArray_${arrayElement.internalTypeId}()
|
|
192
|
-
)`;
|
|
193
|
-
} else if (isDynamic) {
|
|
194
|
-
return `${field.typeWrap}(${field.internalTypeId}(_blob))`;
|
|
195
|
-
} else {
|
|
196
|
-
return renderDecodeValueType(field, 0);
|
|
197
|
-
}
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
// src/render-solidity/record.ts
|
|
201
|
-
function renderRecordMethods(options) {
|
|
202
|
-
const { staticFields, dynamicFields, structName, storeArgument } = options;
|
|
203
|
-
const { _tableId, _typedTableId, _keyArgs, _typedKeyArgs, _primaryKeysDefinition } = renderCommonData(options);
|
|
204
|
-
let result = `
|
|
205
|
-
/** Get the full data */
|
|
206
|
-
function get(${renderArguments([_typedTableId, _typedKeyArgs])}) internal view returns (${renderDecodedRecord(
|
|
207
|
-
options
|
|
208
|
-
)}) {
|
|
209
|
-
${_primaryKeysDefinition}
|
|
210
|
-
bytes memory _blob = StoreSwitch.getRecord(_tableId, _primaryKeys, getSchema());
|
|
211
|
-
return decode(_blob);
|
|
212
|
-
}
|
|
213
|
-
`;
|
|
214
|
-
if (storeArgument) {
|
|
215
|
-
result += `
|
|
216
|
-
/** Get the full data from the specified store */
|
|
217
|
-
function get(${renderArguments([
|
|
218
|
-
_typedTableId,
|
|
219
|
-
`IStore _store`,
|
|
220
|
-
_typedKeyArgs
|
|
221
|
-
])}) internal view returns (${renderDecodedRecord(options)}) {
|
|
222
|
-
${_primaryKeysDefinition}
|
|
223
|
-
bytes memory _blob = _store.getRecord(_tableId, _primaryKeys);
|
|
224
|
-
return decode(_blob);
|
|
225
|
-
}
|
|
226
|
-
`;
|
|
227
|
-
}
|
|
228
|
-
result += `
|
|
229
|
-
/** Set the full data using individual values */
|
|
230
|
-
function set(${renderArguments([
|
|
231
|
-
_typedTableId,
|
|
232
|
-
_typedKeyArgs,
|
|
233
|
-
renderArguments(options.fields.map(({ name, typeWithLocation }) => `${typeWithLocation} ${name}`))
|
|
234
|
-
])}) internal {
|
|
235
|
-
${renderEncodedLengths(dynamicFields)}
|
|
236
|
-
bytes memory _data = abi.encodePacked(${renderArguments([
|
|
237
|
-
renderArguments(staticFields.map(({ name }) => name)),
|
|
238
|
-
// TODO try gas optimization (preallocate for all, encodePacked statics, and direct encode dynamics)
|
|
239
|
-
// (see https://github.com/latticexyz/mud/issues/444)
|
|
240
|
-
...dynamicFields.length === 0 ? [] : ["_encodedLengths.unwrap()", renderArguments(dynamicFields.map((field) => renderEncodeField(field)))]
|
|
241
|
-
])});
|
|
242
|
-
|
|
243
|
-
${_primaryKeysDefinition}
|
|
244
|
-
|
|
245
|
-
StoreSwitch.setRecord(_tableId, _primaryKeys, _data);
|
|
246
|
-
}
|
|
247
|
-
`;
|
|
248
|
-
if (structName !== void 0) {
|
|
249
|
-
result += `
|
|
250
|
-
/** Set the full data using the data struct */
|
|
251
|
-
function set(${renderArguments([_typedTableId, _typedKeyArgs, `${structName} memory _table`])}) internal {
|
|
252
|
-
set(${renderArguments([
|
|
253
|
-
_tableId,
|
|
254
|
-
_keyArgs,
|
|
255
|
-
renderArguments(options.fields.map(({ name }) => `_table.${name}`))
|
|
256
|
-
])});
|
|
257
|
-
}
|
|
258
|
-
`;
|
|
259
|
-
}
|
|
260
|
-
result += renderDecodeFunction(options);
|
|
261
|
-
return result;
|
|
262
|
-
}
|
|
263
|
-
function renderDecodeFunction({ structName, fields, staticFields, dynamicFields }) {
|
|
264
|
-
const renderedDecodedRecord = structName ? `${structName} memory _table` : renderArguments(fields.map(({ name, typeWithLocation }) => `${typeWithLocation} ${name}`));
|
|
265
|
-
const fieldNamePrefix = structName ? "_table." : "";
|
|
266
|
-
const staticOffsets = staticFields.map(() => 0);
|
|
267
|
-
let _acc = 0;
|
|
268
|
-
for (const [index, field] of staticFields.entries()) {
|
|
269
|
-
staticOffsets[index] = _acc;
|
|
270
|
-
_acc += field.staticByteLength;
|
|
271
|
-
}
|
|
272
|
-
if (dynamicFields.length > 0) {
|
|
273
|
-
const totalStaticLength = staticFields.reduce((acc, { staticByteLength }) => acc + staticByteLength, 0);
|
|
274
|
-
return `
|
|
275
|
-
/** Decode the tightly packed blob using this table's schema */
|
|
276
|
-
function decode(bytes memory _blob) internal view returns (${renderedDecodedRecord}) {
|
|
277
|
-
// ${totalStaticLength} is the total byte length of static data
|
|
278
|
-
PackedCounter _encodedLengths = PackedCounter.wrap(Bytes.slice32(_blob, ${totalStaticLength}));
|
|
279
|
-
|
|
280
|
-
${renderList(
|
|
281
|
-
staticFields,
|
|
282
|
-
(field, index) => `
|
|
283
|
-
${fieldNamePrefix}${field.name} = ${renderDecodeValueType(field, staticOffsets[index])};
|
|
284
|
-
`
|
|
285
|
-
)}
|
|
286
|
-
uint256 _start;
|
|
287
|
-
uint256 _end = ${totalStaticLength + 32};
|
|
288
|
-
${renderList(
|
|
289
|
-
dynamicFields,
|
|
290
|
-
(field, index) => `
|
|
291
|
-
_start = _end;
|
|
292
|
-
_end += _encodedLengths.atIndex(${index});
|
|
293
|
-
${fieldNamePrefix}${field.name} = ${renderDecodeDynamicFieldPartial(field)};
|
|
294
|
-
`
|
|
295
|
-
)}
|
|
296
|
-
}
|
|
297
|
-
`;
|
|
298
|
-
} else {
|
|
299
|
-
return `
|
|
300
|
-
/** Decode the tightly packed blob using this table's schema */
|
|
301
|
-
function decode(bytes memory _blob) internal pure returns (${renderedDecodedRecord}) {
|
|
302
|
-
${renderList(
|
|
303
|
-
staticFields,
|
|
304
|
-
(field, index) => `
|
|
305
|
-
${fieldNamePrefix}${field.name} = ${renderDecodeValueType(field, staticOffsets[index])};
|
|
306
|
-
`
|
|
307
|
-
)}
|
|
308
|
-
}
|
|
309
|
-
`;
|
|
310
|
-
}
|
|
311
|
-
}
|
|
312
|
-
function renderDecodedRecord({ structName, fields }) {
|
|
313
|
-
if (structName) {
|
|
314
|
-
return `${structName} memory _table`;
|
|
315
|
-
} else {
|
|
316
|
-
return renderArguments(fields.map(({ name, typeWithLocation }) => `${typeWithLocation} ${name}`));
|
|
317
|
-
}
|
|
318
|
-
}
|
|
319
|
-
function renderDecodeDynamicFieldPartial(field) {
|
|
320
|
-
const { typeId, arrayElement } = field;
|
|
321
|
-
if (arrayElement) {
|
|
322
|
-
return `SliceLib.getSubslice(_blob, _start, _end).decodeArray_${arrayElement.typeId}()`;
|
|
323
|
-
} else {
|
|
324
|
-
return `${typeId}(SliceLib.getSubslice(_blob, _start, _end).toBytes())`;
|
|
325
|
-
}
|
|
326
|
-
}
|
|
327
|
-
function renderEncodedLengths(dynamicFields) {
|
|
328
|
-
if (dynamicFields.length > 0) {
|
|
329
|
-
return `
|
|
330
|
-
uint16[] memory _counters = new uint16[](${dynamicFields.length});
|
|
331
|
-
${renderList(dynamicFields, ({ name, arrayElement }, index) => {
|
|
332
|
-
if (arrayElement) {
|
|
333
|
-
return `_counters[${index}] = uint16(${name}.length * ${arrayElement.staticByteLength});`;
|
|
334
|
-
} else {
|
|
335
|
-
return `_counters[${index}] = uint16(bytes(${name}).length);`;
|
|
336
|
-
}
|
|
337
|
-
})}
|
|
338
|
-
PackedCounter _encodedLengths = PackedCounterLib.pack(_counters);
|
|
339
|
-
`;
|
|
340
|
-
} else {
|
|
341
|
-
return "";
|
|
342
|
-
}
|
|
343
|
-
}
|
|
344
|
-
|
|
345
|
-
// src/render-solidity/renderTable.ts
|
|
346
|
-
function renderTable(options) {
|
|
347
|
-
const { imports, libraryName, structName, staticRouteData, storeImportPath, fields, withRecordMethods } = options;
|
|
348
|
-
const { _typedTableId, _typedKeyArgs, _primaryKeysDefinition } = renderCommonData(options);
|
|
349
|
-
return `${renderedSolidityHeader}
|
|
350
|
-
|
|
351
|
-
// Import schema type
|
|
352
|
-
import { SchemaType } from "@latticexyz/schema-type/src/solidity/SchemaType.sol";
|
|
353
|
-
|
|
354
|
-
// Import store internals
|
|
355
|
-
import { IStore } from "${storeImportPath}IStore.sol";
|
|
356
|
-
import { StoreSwitch } from "${storeImportPath}StoreSwitch.sol";
|
|
357
|
-
import { StoreCore } from "${storeImportPath}StoreCore.sol";
|
|
358
|
-
import { Bytes } from "${storeImportPath}Bytes.sol";
|
|
359
|
-
import { SliceLib } from "${storeImportPath}Slice.sol";
|
|
360
|
-
import { EncodeArray } from "${storeImportPath}tightcoder/EncodeArray.sol";
|
|
361
|
-
import { Schema, SchemaLib } from "${storeImportPath}Schema.sol";
|
|
362
|
-
import { PackedCounter, PackedCounterLib } from "${storeImportPath}PackedCounter.sol";
|
|
363
|
-
|
|
364
|
-
${imports.length > 0 ? `
|
|
365
|
-
// Import user types
|
|
366
|
-
${renderImports(imports)}
|
|
367
|
-
` : ""}
|
|
368
|
-
|
|
369
|
-
${!staticRouteData ? "" : `
|
|
370
|
-
uint256 constant _tableId = uint256(keccak256("${staticRouteData.baseRoute + staticRouteData.subRoute}"));
|
|
371
|
-
uint256 constant ${staticRouteData.tableIdName} = _tableId;
|
|
372
|
-
`}
|
|
373
|
-
|
|
374
|
-
${!structName ? "" : `
|
|
375
|
-
struct ${structName} {
|
|
376
|
-
${renderList(fields, ({ name, typeId }) => `${typeId} ${name};`)}
|
|
377
|
-
}
|
|
378
|
-
`}
|
|
379
|
-
|
|
380
|
-
library ${libraryName} {
|
|
381
|
-
/** Get the table's schema */
|
|
382
|
-
function getSchema() internal pure returns (Schema) {
|
|
383
|
-
SchemaType[] memory _schema = new SchemaType[](${fields.length});
|
|
384
|
-
${renderList(fields, ({ enumName }, index) => `_schema[${index}] = SchemaType.${enumName};`)}
|
|
385
|
-
|
|
386
|
-
return SchemaLib.encode(_schema);
|
|
387
|
-
}
|
|
388
|
-
|
|
389
|
-
/** Get the table's metadata */
|
|
390
|
-
function getMetadata() internal pure returns (string memory, string[] memory) {
|
|
391
|
-
string[] memory _fieldNames = new string[](${fields.length});
|
|
392
|
-
${renderList(fields, (field, index) => `_fieldNames[${index}] = "${field.name}";`)}
|
|
393
|
-
return ("${libraryName}", _fieldNames);
|
|
394
|
-
}
|
|
395
|
-
|
|
396
|
-
/** Register the table's schema */
|
|
397
|
-
function registerSchema(${_typedTableId}) internal {
|
|
398
|
-
StoreSwitch.registerSchema(_tableId, getSchema());
|
|
399
|
-
}
|
|
400
|
-
|
|
401
|
-
/** Set the table's metadata */
|
|
402
|
-
function setMetadata(${_typedTableId}) internal {
|
|
403
|
-
(string memory _tableName, string[] memory _fieldNames) = getMetadata();
|
|
404
|
-
StoreSwitch.setMetadata(_tableId, _tableName, _fieldNames);
|
|
405
|
-
}
|
|
406
|
-
|
|
407
|
-
${!options.storeArgument ? "" : `
|
|
408
|
-
/** Register the table's schema for the specified store */
|
|
409
|
-
function registerSchema(${renderArguments([_typedTableId, "IStore _store"])}) internal {
|
|
410
|
-
_store.registerSchema(_tableId, getSchema());
|
|
411
|
-
}
|
|
412
|
-
|
|
413
|
-
/** Set the table's metadata for the specified store */
|
|
414
|
-
function setMetadata(${renderArguments([_typedTableId, "IStore _store"])}) internal {
|
|
415
|
-
(string memory _tableName, string[] memory _fieldNames) = getMetadata();
|
|
416
|
-
_store.setMetadata(_tableId, _tableName, _fieldNames);
|
|
417
|
-
}
|
|
418
|
-
`}
|
|
419
|
-
|
|
420
|
-
${renderFieldMethods(options)}
|
|
421
|
-
|
|
422
|
-
${withRecordMethods ? renderRecordMethods(options) : ""}
|
|
423
|
-
|
|
424
|
-
/* Delete all data for given keys */
|
|
425
|
-
function deleteRecord(${renderArguments([_typedTableId, _typedKeyArgs])}) internal {
|
|
426
|
-
${_primaryKeysDefinition}
|
|
427
|
-
StoreSwitch.deleteRecord(_tableId, _primaryKeys);
|
|
428
|
-
}
|
|
429
|
-
}
|
|
430
|
-
|
|
431
|
-
${// nothing can be cast to bool, so an assembly helper is required
|
|
432
|
-
!fields.some(({ typeId }) => typeId === "bool") ? "" : `
|
|
433
|
-
function _toBool(uint8 value) pure returns (bool result) {
|
|
434
|
-
assembly {
|
|
435
|
-
result := value
|
|
436
|
-
}
|
|
437
|
-
}
|
|
438
|
-
`}
|
|
439
|
-
|
|
440
|
-
${// nothing can be cast from bool, so an assembly helper is required
|
|
441
|
-
!options.primaryKeys.some(({ typeId }) => typeId === "bool") ? "" : `
|
|
442
|
-
function _boolToBytes32(bool value) pure returns (bytes32 result) {
|
|
443
|
-
assembly {
|
|
444
|
-
result := value
|
|
445
|
-
}
|
|
446
|
-
}
|
|
447
|
-
`}
|
|
448
|
-
|
|
449
|
-
`;
|
|
450
|
-
}
|
|
451
|
-
|
|
452
|
-
// src/render-solidity/renderTablesFromConfig.ts
|
|
453
|
-
import path from "path";
|
|
454
|
-
function renderTablesFromConfig(config, srcDirectory) {
|
|
455
|
-
const storeImportPath = config.storeImportPath;
|
|
456
|
-
const renderedTables = [];
|
|
457
|
-
for (const tableName of Object.keys(config.tables)) {
|
|
458
|
-
const tableData = config.tables[tableName];
|
|
459
|
-
const outputDirectory = path.join(srcDirectory, tableData.directory);
|
|
460
|
-
const withStruct = tableData.dataStruct;
|
|
461
|
-
const withRecordMethods = withStruct || Object.keys(tableData.schema).length > 1;
|
|
462
|
-
const noFieldMethodSuffix = !withRecordMethods && Object.keys(tableData.schema).length === 1;
|
|
463
|
-
const imports = [];
|
|
464
|
-
const primaryKeys = Object.keys(tableData.primaryKeys).map((name) => {
|
|
465
|
-
const schemaOrUserType = tableData.primaryKeys[name];
|
|
466
|
-
const { renderTableType, importDatum } = resolveSchemaOrUserType(
|
|
467
|
-
schemaOrUserType,
|
|
468
|
-
srcDirectory,
|
|
469
|
-
outputDirectory,
|
|
470
|
-
config.userTypes
|
|
471
|
-
);
|
|
472
|
-
if (importDatum)
|
|
473
|
-
imports.push(importDatum);
|
|
474
|
-
if (renderTableType.isDynamic)
|
|
475
|
-
throw new Error(`Parsing error: found dynamic primary key ${name} in table ${tableName}`);
|
|
476
|
-
const primaryKey = {
|
|
477
|
-
...renderTableType,
|
|
478
|
-
name,
|
|
479
|
-
isDynamic: false
|
|
480
|
-
};
|
|
481
|
-
return primaryKey;
|
|
482
|
-
});
|
|
483
|
-
const fields = Object.keys(tableData.schema).map((name) => {
|
|
484
|
-
const schemaOrUserType = tableData.schema[name];
|
|
485
|
-
const { renderTableType, importDatum, schemaType } = resolveSchemaOrUserType(
|
|
486
|
-
schemaOrUserType,
|
|
487
|
-
srcDirectory,
|
|
488
|
-
outputDirectory,
|
|
489
|
-
config.userTypes
|
|
490
|
-
);
|
|
491
|
-
if (importDatum)
|
|
492
|
-
imports.push(importDatum);
|
|
493
|
-
const elementType = SchemaTypeArrayToElement[schemaType];
|
|
494
|
-
const field = {
|
|
495
|
-
...renderTableType,
|
|
496
|
-
arrayElement: elementType !== void 0 ? getSchemaTypeInfo(elementType) : void 0,
|
|
497
|
-
name,
|
|
498
|
-
methodNameSuffix: noFieldMethodSuffix ? "" : `${name[0].toUpperCase()}${name.slice(1)}`
|
|
499
|
-
};
|
|
500
|
-
return field;
|
|
501
|
-
});
|
|
502
|
-
const staticFields = fields.filter(({ isDynamic }) => !isDynamic);
|
|
503
|
-
const dynamicFields = fields.filter(({ isDynamic }) => isDynamic);
|
|
504
|
-
const staticRouteData = (() => {
|
|
505
|
-
if (tableData.tableIdArgument) {
|
|
506
|
-
return;
|
|
507
|
-
} else {
|
|
508
|
-
return {
|
|
509
|
-
tableIdName: tableName + "TableId",
|
|
510
|
-
baseRoute: config.baseRoute,
|
|
511
|
-
subRoute: tableData.route
|
|
512
|
-
};
|
|
513
|
-
}
|
|
514
|
-
})();
|
|
515
|
-
renderedTables.push({
|
|
516
|
-
outputDirectory,
|
|
517
|
-
tableName,
|
|
518
|
-
tableData,
|
|
519
|
-
output: renderTable({
|
|
520
|
-
imports,
|
|
521
|
-
libraryName: tableName,
|
|
522
|
-
structName: withStruct ? tableName + "Data" : void 0,
|
|
523
|
-
staticRouteData,
|
|
524
|
-
storeImportPath,
|
|
525
|
-
primaryKeys,
|
|
526
|
-
fields,
|
|
527
|
-
staticFields,
|
|
528
|
-
dynamicFields,
|
|
529
|
-
withRecordMethods,
|
|
530
|
-
storeArgument: tableData.storeArgument
|
|
531
|
-
})
|
|
532
|
-
});
|
|
533
|
-
}
|
|
534
|
-
return renderedTables;
|
|
535
|
-
}
|
|
536
|
-
|
|
537
|
-
// src/constants.ts
|
|
538
|
-
var deploymentInfoFilenamePrefix = "mud-deployment-";
|
|
539
|
-
|
|
540
|
-
export {
|
|
541
|
-
renderedSolidityHeader,
|
|
542
|
-
renderList,
|
|
543
|
-
renderArguments,
|
|
544
|
-
renderTable,
|
|
545
|
-
renderTablesFromConfig,
|
|
546
|
-
deploymentInfoFilenamePrefix
|
|
547
|
-
};
|