@alephium/web3 0.41.0 → 0.42.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/alephium-web3.min.js +1 -1
- package/dist/alephium-web3.min.js.map +1 -1
- package/dist/src/contract/contract.d.ts +8 -95
- package/dist/src/contract/contract.js +11 -544
- package/dist/src/transaction/index.d.ts +1 -0
- package/dist/src/transaction/index.js +1 -0
- package/dist/src/transaction/utils.d.ts +2 -0
- package/dist/src/transaction/utils.js +34 -0
- package/package.json +1 -1
- package/src/contract/contract.ts +15 -783
- package/src/transaction/index.ts +1 -0
- package/src/transaction/utils.ts +38 -0
- package/webpack.config.js +0 -1
- package/dist/src/utils/error.d.ts +0 -15
- package/dist/src/utils/error.js +0 -66
- package/src/utils/error.ts +0 -77
|
@@ -39,35 +39,21 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
|
|
39
39
|
__setModuleDefault(result, mod);
|
|
40
40
|
return result;
|
|
41
41
|
};
|
|
42
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
43
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
44
|
-
};
|
|
45
42
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
46
|
-
exports.getTokenIdFromUnsignedTx = exports.getContractIdFromUnsignedTx = exports.getContractEventsCurrentCount = exports.multicallMethods = exports.callMethod = exports.subscribeContractEvents = exports.subscribeContractEvent = exports.decodeEvent = exports.subscribeContractDestroyedEvent = exports.subscribeContractCreatedEvent = exports.fetchContractState = exports.ContractInstance = exports.getMapItem = exports.RalphMap = exports.testMethod = exports.addStdIdToFields = exports.subscribeEventsFromContract = exports.decodeContractDestroyedEvent = exports.decodeContractCreatedEvent = exports.DestroyContractEventAddresses = exports.CreateContractEventAddresses = exports.ExecutableScript = exports.ContractFactory = exports.randomTxId = exports.fromApiEventFields = exports.fromApiArray = exports.getDefaultValue = exports.fromApiFields = exports.Script = exports.Contract = exports.Artifact = exports.
|
|
43
|
+
exports.getTokenIdFromUnsignedTx = exports.getContractIdFromUnsignedTx = exports.getContractEventsCurrentCount = exports.multicallMethods = exports.callMethod = exports.subscribeContractEvents = exports.subscribeContractEvent = exports.decodeEvent = exports.subscribeContractDestroyedEvent = exports.subscribeContractCreatedEvent = exports.fetchContractState = exports.ContractInstance = exports.getMapItem = exports.RalphMap = exports.testMethod = exports.addStdIdToFields = exports.subscribeEventsFromContract = exports.decodeContractDestroyedEvent = exports.decodeContractCreatedEvent = exports.DestroyContractEventAddresses = exports.CreateContractEventAddresses = exports.ExecutableScript = exports.ContractFactory = exports.randomTxId = exports.fromApiEventFields = exports.fromApiArray = exports.getDefaultValue = exports.fromApiFields = exports.Script = exports.Contract = exports.Artifact = exports.Struct = exports.DEFAULT_COMPILER_OPTIONS = exports.DEFAULT_NODE_COMPILER_OPTIONS = exports.StdIdFieldName = void 0;
|
|
47
44
|
const buffer_1 = require("buffer/");
|
|
48
|
-
const fs_1 =
|
|
49
|
-
const fs_2 = require("fs");
|
|
45
|
+
const fs_1 = require("fs");
|
|
50
46
|
const api_1 = require("../api");
|
|
51
47
|
const ralph = __importStar(require("./ralph"));
|
|
52
48
|
const utils_1 = require("../utils");
|
|
53
49
|
const global_1 = require("../global");
|
|
54
|
-
const path = __importStar(require("path"));
|
|
55
50
|
const events_1 = require("./events");
|
|
56
51
|
const constants_1 = require("../constants");
|
|
57
52
|
const blake = __importStar(require("blakejs"));
|
|
58
|
-
const error_1 = require("../utils/error");
|
|
59
53
|
const debug_1 = require("../debug");
|
|
60
54
|
const codec_1 = require("../codec");
|
|
61
55
|
const crypto = new utils_1.WebCrypto();
|
|
62
56
|
exports.StdIdFieldName = '__stdInterfaceId';
|
|
63
|
-
var SourceKind;
|
|
64
|
-
(function (SourceKind) {
|
|
65
|
-
SourceKind[SourceKind["Contract"] = 0] = "Contract";
|
|
66
|
-
SourceKind[SourceKind["Script"] = 1] = "Script";
|
|
67
|
-
SourceKind[SourceKind["AbstractContract"] = 2] = "AbstractContract";
|
|
68
|
-
SourceKind[SourceKind["Interface"] = 3] = "Interface";
|
|
69
|
-
SourceKind[SourceKind["Struct"] = 4] = "Struct";
|
|
70
|
-
})(SourceKind || (SourceKind = {}));
|
|
71
57
|
exports.DEFAULT_NODE_COMPILER_OPTIONS = {
|
|
72
58
|
ignoreUnusedConstantsWarnings: false,
|
|
73
59
|
ignoreUnusedVariablesWarnings: false,
|
|
@@ -77,175 +63,6 @@ exports.DEFAULT_NODE_COMPILER_OPTIONS = {
|
|
|
77
63
|
ignoreCheckExternalCallerWarnings: false
|
|
78
64
|
};
|
|
79
65
|
exports.DEFAULT_COMPILER_OPTIONS = { errorOnWarnings: true, ...exports.DEFAULT_NODE_COMPILER_OPTIONS };
|
|
80
|
-
class TypedMatcher {
|
|
81
|
-
constructor(pattern, type) {
|
|
82
|
-
this.matcher = new RegExp(pattern, 'mg');
|
|
83
|
-
this.type = type;
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
function removeParentsPrefix(parts) {
|
|
87
|
-
let index = 0;
|
|
88
|
-
for (let i = 0; i < parts.length; i++) {
|
|
89
|
-
if (parts[`${i}`] === '..') {
|
|
90
|
-
index += 1;
|
|
91
|
-
}
|
|
92
|
-
else {
|
|
93
|
-
break;
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
return path.join(...parts.slice(index));
|
|
97
|
-
}
|
|
98
|
-
class SourceInfo {
|
|
99
|
-
getArtifactPath(artifactsRootDir) {
|
|
100
|
-
let fullPath;
|
|
101
|
-
if (this.isExternal) {
|
|
102
|
-
const relativePath = removeParentsPrefix(this.contractRelativePath.split(path.sep));
|
|
103
|
-
const externalPath = path.join('.external', relativePath);
|
|
104
|
-
fullPath = path.join(artifactsRootDir, externalPath);
|
|
105
|
-
}
|
|
106
|
-
else {
|
|
107
|
-
fullPath = path.join(artifactsRootDir, this.contractRelativePath);
|
|
108
|
-
}
|
|
109
|
-
return path.join(path.dirname(fullPath), `${this.name}.ral.json`);
|
|
110
|
-
}
|
|
111
|
-
constructor(type, name, sourceCode, sourceCodeHash, contractRelativePath, isExternal) {
|
|
112
|
-
this.type = type;
|
|
113
|
-
this.name = name;
|
|
114
|
-
this.sourceCode = sourceCode;
|
|
115
|
-
this.sourceCodeHash = sourceCodeHash;
|
|
116
|
-
this.contractRelativePath = contractRelativePath;
|
|
117
|
-
this.isExternal = isExternal;
|
|
118
|
-
}
|
|
119
|
-
static async from(type, name, sourceCode, contractRelativePath, isExternal) {
|
|
120
|
-
const sourceCodeHash = await crypto.subtle.digest('SHA-256', buffer_1.Buffer.from(sourceCode));
|
|
121
|
-
const sourceCodeHashHex = buffer_1.Buffer.from(sourceCodeHash).toString('hex');
|
|
122
|
-
return new SourceInfo(type, name, sourceCode, sourceCodeHashHex, contractRelativePath, isExternal);
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
class Compiled {
|
|
126
|
-
constructor(sourceInfo, artifact, warnings) {
|
|
127
|
-
this.sourceInfo = sourceInfo;
|
|
128
|
-
this.artifact = artifact;
|
|
129
|
-
this.warnings = warnings;
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
function findSourceInfoAtLineNumber(sources, line) {
|
|
133
|
-
let currentLine = 0;
|
|
134
|
-
const sourceInfosWithLine = sources.map((source) => {
|
|
135
|
-
const startIndex = currentLine + 1;
|
|
136
|
-
currentLine += source.sourceCode.split('\n').length;
|
|
137
|
-
const endIndex = currentLine;
|
|
138
|
-
return { sourceInfo: source, startIndex: startIndex, endIndex: endIndex };
|
|
139
|
-
});
|
|
140
|
-
const sourceInfo = sourceInfosWithLine.find((sourceInfoWithLine) => {
|
|
141
|
-
return line >= sourceInfoWithLine.startIndex && line <= sourceInfoWithLine.endIndex;
|
|
142
|
-
});
|
|
143
|
-
return sourceInfo;
|
|
144
|
-
}
|
|
145
|
-
class ProjectArtifact {
|
|
146
|
-
static checkCompilerOptionsParameter(compilerOptions) {
|
|
147
|
-
if (Object.keys(compilerOptions).length != Object.keys(exports.DEFAULT_NODE_COMPILER_OPTIONS).length) {
|
|
148
|
-
throw Error(`Not all compiler options are set: ${compilerOptions}`);
|
|
149
|
-
}
|
|
150
|
-
const combined = { ...compilerOptions, ...exports.DEFAULT_NODE_COMPILER_OPTIONS };
|
|
151
|
-
if (Object.keys(combined).length !== Object.keys(exports.DEFAULT_NODE_COMPILER_OPTIONS).length) {
|
|
152
|
-
throw Error(`There are unknown compiler options: ${compilerOptions}`);
|
|
153
|
-
}
|
|
154
|
-
}
|
|
155
|
-
constructor(fullNodeVersion, compilerOptionsUsed, infos) {
|
|
156
|
-
ProjectArtifact.checkCompilerOptionsParameter(compilerOptionsUsed);
|
|
157
|
-
this.fullNodeVersion = fullNodeVersion;
|
|
158
|
-
this.compilerOptionsUsed = compilerOptionsUsed;
|
|
159
|
-
this.infos = infos;
|
|
160
|
-
}
|
|
161
|
-
static isCodeChanged(current, previous) {
|
|
162
|
-
if (current.infos.size !== previous.infos.size) {
|
|
163
|
-
return true;
|
|
164
|
-
}
|
|
165
|
-
for (const [name, codeInfo] of current.infos) {
|
|
166
|
-
const prevCodeInfo = previous.infos.get(name);
|
|
167
|
-
if (prevCodeInfo?.codeHashDebug !== codeInfo.codeHashDebug) {
|
|
168
|
-
return true;
|
|
169
|
-
}
|
|
170
|
-
}
|
|
171
|
-
return false;
|
|
172
|
-
}
|
|
173
|
-
async saveToFile(rootPath) {
|
|
174
|
-
const filepath = path.join(rootPath, ProjectArtifact.artifactFileName);
|
|
175
|
-
const artifact = {
|
|
176
|
-
fullNodeVersion: this.fullNodeVersion,
|
|
177
|
-
compilerOptionsUsed: this.compilerOptionsUsed,
|
|
178
|
-
infos: Object.fromEntries(new Map([...this.infos].sort()))
|
|
179
|
-
};
|
|
180
|
-
const content = JSON.stringify(artifact, null, 2);
|
|
181
|
-
return fs_2.promises.writeFile(filepath, content);
|
|
182
|
-
}
|
|
183
|
-
getChangedSources(sourceInfos) {
|
|
184
|
-
const result = [];
|
|
185
|
-
for (const sourceInfo of sourceInfos) {
|
|
186
|
-
const info = this.infos.get(sourceInfo.name);
|
|
187
|
-
if (typeof info === 'undefined' || info.sourceCodeHash !== sourceInfo.sourceCodeHash) {
|
|
188
|
-
result.push(sourceInfo);
|
|
189
|
-
}
|
|
190
|
-
}
|
|
191
|
-
return result;
|
|
192
|
-
}
|
|
193
|
-
needToReCompile(compilerOptions, fullNodeVersion) {
|
|
194
|
-
ProjectArtifact.checkCompilerOptionsParameter(compilerOptions);
|
|
195
|
-
if (this.fullNodeVersion !== fullNodeVersion) {
|
|
196
|
-
return true;
|
|
197
|
-
}
|
|
198
|
-
const optionsMatched = Object.entries(compilerOptions).every(([key, inputOption]) => {
|
|
199
|
-
const usedOption = this.compilerOptionsUsed[`${key}`];
|
|
200
|
-
return usedOption === inputOption;
|
|
201
|
-
});
|
|
202
|
-
if (!optionsMatched) {
|
|
203
|
-
return true;
|
|
204
|
-
}
|
|
205
|
-
return false;
|
|
206
|
-
}
|
|
207
|
-
static async from(rootPath) {
|
|
208
|
-
const filepath = path.join(rootPath, ProjectArtifact.artifactFileName);
|
|
209
|
-
if (!fs_1.default.existsSync(filepath)) {
|
|
210
|
-
return undefined;
|
|
211
|
-
}
|
|
212
|
-
try {
|
|
213
|
-
const content = await fs_2.promises.readFile(filepath);
|
|
214
|
-
const json = JSON.parse(content.toString());
|
|
215
|
-
const fullNodeVersion = json.fullNodeVersion;
|
|
216
|
-
const compilerOptionsUsed = json.compilerOptionsUsed;
|
|
217
|
-
const files = new Map(Object.entries(json.infos));
|
|
218
|
-
return new ProjectArtifact(fullNodeVersion, compilerOptionsUsed, files);
|
|
219
|
-
}
|
|
220
|
-
catch (error) {
|
|
221
|
-
console.error(`Failed to load project artifact, error: ${error}`);
|
|
222
|
-
return undefined;
|
|
223
|
-
}
|
|
224
|
-
}
|
|
225
|
-
}
|
|
226
|
-
exports.ProjectArtifact = ProjectArtifact;
|
|
227
|
-
ProjectArtifact.artifactFileName = '.project.json';
|
|
228
|
-
function removeOldArtifacts(dir, sourceFiles) {
|
|
229
|
-
const files = fs_1.default.readdirSync(dir);
|
|
230
|
-
files.forEach((file) => {
|
|
231
|
-
const filePath = path.join(dir, file);
|
|
232
|
-
const stat = fs_1.default.statSync(filePath);
|
|
233
|
-
if (stat.isDirectory()) {
|
|
234
|
-
removeOldArtifacts(filePath, sourceFiles);
|
|
235
|
-
}
|
|
236
|
-
else if (filePath.endsWith('.ral.json') || filePath.endsWith('.ral')) {
|
|
237
|
-
const filename = path.basename(filePath);
|
|
238
|
-
const artifactName = filename.slice(0, filename.indexOf('.'));
|
|
239
|
-
const sourceFile = sourceFiles.find((s) => s.name === artifactName && (s.type === SourceKind.Contract || s.type === SourceKind.Script));
|
|
240
|
-
if (sourceFile === undefined) {
|
|
241
|
-
fs_1.default.unlinkSync(filePath);
|
|
242
|
-
}
|
|
243
|
-
}
|
|
244
|
-
});
|
|
245
|
-
if (fs_1.default.readdirSync(dir).length === 0) {
|
|
246
|
-
fs_1.default.rmdirSync(dir);
|
|
247
|
-
}
|
|
248
|
-
}
|
|
249
66
|
class Struct {
|
|
250
67
|
constructor(name, fieldNames, fieldTypes, isMutable) {
|
|
251
68
|
this.name = name;
|
|
@@ -272,352 +89,6 @@ class Struct {
|
|
|
272
89
|
}
|
|
273
90
|
}
|
|
274
91
|
exports.Struct = Struct;
|
|
275
|
-
class Project {
|
|
276
|
-
static buildProjectArtifact(fullNodeVersion, sourceInfos, contracts, scripts, compilerOptions) {
|
|
277
|
-
const files = new Map();
|
|
278
|
-
contracts.forEach((c) => {
|
|
279
|
-
files.set(c.artifact.name, {
|
|
280
|
-
sourceFile: c.sourceInfo.contractRelativePath,
|
|
281
|
-
sourceCodeHash: c.sourceInfo.sourceCodeHash,
|
|
282
|
-
bytecodeDebugPatch: c.artifact.bytecodeDebugPatch,
|
|
283
|
-
codeHashDebug: c.artifact.codeHashDebug,
|
|
284
|
-
warnings: c.warnings
|
|
285
|
-
});
|
|
286
|
-
});
|
|
287
|
-
scripts.forEach((s) => {
|
|
288
|
-
files.set(s.artifact.name, {
|
|
289
|
-
sourceFile: s.sourceInfo.contractRelativePath,
|
|
290
|
-
sourceCodeHash: s.sourceInfo.sourceCodeHash,
|
|
291
|
-
bytecodeDebugPatch: s.artifact.bytecodeDebugPatch,
|
|
292
|
-
codeHashDebug: '',
|
|
293
|
-
warnings: s.warnings
|
|
294
|
-
});
|
|
295
|
-
});
|
|
296
|
-
const compiledSize = contracts.size + scripts.size;
|
|
297
|
-
sourceInfos.slice(compiledSize).forEach((c) => {
|
|
298
|
-
files.set(c.name, {
|
|
299
|
-
sourceFile: c.contractRelativePath,
|
|
300
|
-
sourceCodeHash: c.sourceCodeHash,
|
|
301
|
-
bytecodeDebugPatch: '',
|
|
302
|
-
codeHashDebug: '',
|
|
303
|
-
warnings: []
|
|
304
|
-
});
|
|
305
|
-
});
|
|
306
|
-
return new ProjectArtifact(fullNodeVersion, compilerOptions, files);
|
|
307
|
-
}
|
|
308
|
-
constructor(contractsRootDir, artifactsRootDir, sourceInfos, contracts, scripts, structs, errorOnWarnings, projectArtifact) {
|
|
309
|
-
this.contractsRootDir = contractsRootDir;
|
|
310
|
-
this.artifactsRootDir = artifactsRootDir;
|
|
311
|
-
this.sourceInfos = sourceInfos;
|
|
312
|
-
this.contracts = contracts;
|
|
313
|
-
this.scripts = scripts;
|
|
314
|
-
this.structs = structs;
|
|
315
|
-
this.projectArtifact = projectArtifact;
|
|
316
|
-
if (errorOnWarnings) {
|
|
317
|
-
Project.checkCompilerWarnings([
|
|
318
|
-
...[...contracts.entries()].map((c) => c[1].warnings).flat(),
|
|
319
|
-
...[...scripts.entries()].map((s) => s[1].warnings).flat()
|
|
320
|
-
], errorOnWarnings);
|
|
321
|
-
}
|
|
322
|
-
}
|
|
323
|
-
static checkCompilerWarnings(warnings, errorOnWarnings) {
|
|
324
|
-
if (warnings.length !== 0) {
|
|
325
|
-
const prefixPerWarning = ' - ';
|
|
326
|
-
const warningString = prefixPerWarning + warnings.join('\n' + prefixPerWarning);
|
|
327
|
-
const output = `Compilation warnings:\n` + warningString + '\n';
|
|
328
|
-
if (errorOnWarnings) {
|
|
329
|
-
throw new Error(output);
|
|
330
|
-
}
|
|
331
|
-
else {
|
|
332
|
-
console.log(output);
|
|
333
|
-
}
|
|
334
|
-
}
|
|
335
|
-
}
|
|
336
|
-
static contract(name) {
|
|
337
|
-
const contract = Project.currentProject.contracts.get(name);
|
|
338
|
-
if (typeof contract === 'undefined') {
|
|
339
|
-
throw new Error(`Contract "${name}" does not exist`);
|
|
340
|
-
}
|
|
341
|
-
return contract.artifact;
|
|
342
|
-
}
|
|
343
|
-
static script(name) {
|
|
344
|
-
const script = Project.currentProject.scripts.get(name);
|
|
345
|
-
if (typeof script === 'undefined') {
|
|
346
|
-
throw new Error(`Script "${name}" does not exist`);
|
|
347
|
-
}
|
|
348
|
-
return script.artifact;
|
|
349
|
-
}
|
|
350
|
-
static async loadStructs(artifactsRootDir) {
|
|
351
|
-
const filePath = path.join(artifactsRootDir, 'structs.ral.json');
|
|
352
|
-
if (!fs_1.default.existsSync(filePath))
|
|
353
|
-
return [];
|
|
354
|
-
const content = await fs_2.promises.readFile(filePath);
|
|
355
|
-
const json = JSON.parse(content.toString());
|
|
356
|
-
if (!Array.isArray(json)) {
|
|
357
|
-
throw Error(`Invalid structs JSON: ${content}`);
|
|
358
|
-
}
|
|
359
|
-
return Array.from(json).map((item) => Struct.fromJson(item));
|
|
360
|
-
}
|
|
361
|
-
async saveStructsToFile() {
|
|
362
|
-
if (this.structs.length === 0)
|
|
363
|
-
return;
|
|
364
|
-
const structs = this.structs.map((s) => s.toJson());
|
|
365
|
-
const filePath = path.join(this.artifactsRootDir, 'structs.ral.json');
|
|
366
|
-
return fs_2.promises.writeFile(filePath, JSON.stringify(structs, null, 2));
|
|
367
|
-
}
|
|
368
|
-
async saveArtifactsToFile(projectRootDir, skipSaveArtifacts, changedSources) {
|
|
369
|
-
const artifactsRootDir = this.artifactsRootDir;
|
|
370
|
-
const saveToFile = async function (compiled) {
|
|
371
|
-
const artifactPath = compiled.sourceInfo.getArtifactPath(artifactsRootDir);
|
|
372
|
-
const dirname = path.dirname(artifactPath);
|
|
373
|
-
if (!fs_1.default.existsSync(dirname)) {
|
|
374
|
-
fs_1.default.mkdirSync(dirname, { recursive: true });
|
|
375
|
-
}
|
|
376
|
-
return fs_2.promises.writeFile(artifactPath, compiled.artifact.toString());
|
|
377
|
-
};
|
|
378
|
-
for (const [_, contract] of this.contracts) {
|
|
379
|
-
if (!skipSaveArtifacts || changedSources.find((s) => s.name === contract.sourceInfo.name) !== undefined) {
|
|
380
|
-
await saveToFile(contract);
|
|
381
|
-
}
|
|
382
|
-
}
|
|
383
|
-
for (const [_, script] of this.scripts) {
|
|
384
|
-
await saveToFile(script);
|
|
385
|
-
}
|
|
386
|
-
await this.saveStructsToFile();
|
|
387
|
-
await this.saveProjectArtifact(projectRootDir, skipSaveArtifacts, changedSources);
|
|
388
|
-
}
|
|
389
|
-
async saveProjectArtifact(projectRootDir, skipSaveArtifacts, changedSources) {
|
|
390
|
-
if (skipSaveArtifacts) {
|
|
391
|
-
// we should not update the `codeHashDebug` if the `skipSaveArtifacts` is enabled
|
|
392
|
-
const prevProjectArtifact = await ProjectArtifact.from(projectRootDir);
|
|
393
|
-
if (prevProjectArtifact !== undefined) {
|
|
394
|
-
for (const [name, info] of this.projectArtifact.infos) {
|
|
395
|
-
if (changedSources.find((s) => s.name === name) === undefined) {
|
|
396
|
-
const prevInfo = prevProjectArtifact.infos.get(name);
|
|
397
|
-
info.bytecodeDebugPatch = prevInfo?.bytecodeDebugPatch ?? info.bytecodeDebugPatch;
|
|
398
|
-
info.codeHashDebug = prevInfo?.codeHashDebug ?? info.codeHashDebug;
|
|
399
|
-
}
|
|
400
|
-
}
|
|
401
|
-
}
|
|
402
|
-
}
|
|
403
|
-
await this.projectArtifact.saveToFile(projectRootDir);
|
|
404
|
-
}
|
|
405
|
-
contractByCodeHash(codeHash) {
|
|
406
|
-
const contract = [...this.contracts.values()].find((c) => c.artifact.codeHash === codeHash || c.artifact.codeHashDebug == codeHash);
|
|
407
|
-
if (typeof contract === 'undefined') {
|
|
408
|
-
throw new Error(`Unknown code with code hash: ${codeHash}`);
|
|
409
|
-
}
|
|
410
|
-
return contract.artifact;
|
|
411
|
-
}
|
|
412
|
-
static async getCompileResult(provider, compilerOptions, sources) {
|
|
413
|
-
try {
|
|
414
|
-
const sourceStr = sources.map((f) => f.sourceCode).join('\n');
|
|
415
|
-
return await provider.contracts.postContractsCompileProject({
|
|
416
|
-
code: sourceStr,
|
|
417
|
-
compilerOptions: compilerOptions
|
|
418
|
-
});
|
|
419
|
-
}
|
|
420
|
-
catch (error) {
|
|
421
|
-
if (!(error instanceof Error)) {
|
|
422
|
-
throw error;
|
|
423
|
-
}
|
|
424
|
-
const parsed = (0, error_1.parseError)(error.message);
|
|
425
|
-
if (!parsed) {
|
|
426
|
-
throw error;
|
|
427
|
-
}
|
|
428
|
-
const sourceInfo = findSourceInfoAtLineNumber(sources, parsed.lineStart);
|
|
429
|
-
if (!sourceInfo) {
|
|
430
|
-
throw error;
|
|
431
|
-
}
|
|
432
|
-
const shiftIndex = parsed.lineStart - sourceInfo.startIndex + 1;
|
|
433
|
-
const newError = parsed.reformat(shiftIndex, sourceInfo.sourceInfo.contractRelativePath);
|
|
434
|
-
throw new Error(newError);
|
|
435
|
-
}
|
|
436
|
-
}
|
|
437
|
-
static async compile(fullNodeVersion, provider, sourceInfos, projectRootDir, contractsRootDir, artifactsRootDir, errorOnWarnings, compilerOptions, changedSources, skipSaveArtifacts = false) {
|
|
438
|
-
const removeDuplicates = sourceInfos.reduce((acc, sourceInfo) => {
|
|
439
|
-
if (acc.find((info) => info.sourceCodeHash === sourceInfo.sourceCodeHash) === undefined) {
|
|
440
|
-
acc.push(sourceInfo);
|
|
441
|
-
}
|
|
442
|
-
return acc;
|
|
443
|
-
}, []);
|
|
444
|
-
const result = await Project.getCompileResult(provider, compilerOptions, removeDuplicates);
|
|
445
|
-
const contracts = new Map();
|
|
446
|
-
const scripts = new Map();
|
|
447
|
-
const structs = result.structs === undefined ? [] : result.structs.map((item) => Struct.fromStructSig(item));
|
|
448
|
-
result.contracts.forEach((contractResult) => {
|
|
449
|
-
const sourceInfo = sourceInfos.find((sourceInfo) => sourceInfo.type === SourceKind.Contract && sourceInfo.name === contractResult.name);
|
|
450
|
-
if (sourceInfo === undefined) {
|
|
451
|
-
// this should never happen
|
|
452
|
-
throw new Error(`SourceInfo does not exist for contract ${contractResult.name}`);
|
|
453
|
-
}
|
|
454
|
-
const contract = Contract.fromCompileResult(contractResult, structs);
|
|
455
|
-
contracts.set(contract.name, new Compiled(sourceInfo, contract, contractResult.warnings));
|
|
456
|
-
});
|
|
457
|
-
result.scripts.forEach((scriptResult) => {
|
|
458
|
-
const sourceInfo = sourceInfos.find((sourceInfo) => sourceInfo.type === SourceKind.Script && sourceInfo.name === scriptResult.name);
|
|
459
|
-
if (sourceInfo === undefined) {
|
|
460
|
-
// this should never happen
|
|
461
|
-
throw new Error(`SourceInfo does not exist for script ${scriptResult.name}`);
|
|
462
|
-
}
|
|
463
|
-
const script = Script.fromCompileResult(scriptResult, structs);
|
|
464
|
-
scripts.set(script.name, new Compiled(sourceInfo, script, scriptResult.warnings));
|
|
465
|
-
});
|
|
466
|
-
const projectArtifact = Project.buildProjectArtifact(fullNodeVersion, sourceInfos, contracts, scripts, compilerOptions);
|
|
467
|
-
const project = new Project(contractsRootDir, artifactsRootDir, sourceInfos, contracts, scripts, structs, errorOnWarnings, projectArtifact);
|
|
468
|
-
await project.saveArtifactsToFile(projectRootDir, skipSaveArtifacts, changedSources);
|
|
469
|
-
return project;
|
|
470
|
-
}
|
|
471
|
-
static async loadArtifacts(provider, sourceInfos, projectRootDir, contractsRootDir, artifactsRootDir, errorOnWarnings, compilerOptions) {
|
|
472
|
-
const projectArtifact = await ProjectArtifact.from(projectRootDir);
|
|
473
|
-
if (projectArtifact === undefined) {
|
|
474
|
-
throw Error('Failed to load project artifact');
|
|
475
|
-
}
|
|
476
|
-
try {
|
|
477
|
-
const contracts = new Map();
|
|
478
|
-
const scripts = new Map();
|
|
479
|
-
const structs = await Project.loadStructs(artifactsRootDir);
|
|
480
|
-
for (const sourceInfo of sourceInfos) {
|
|
481
|
-
const info = projectArtifact.infos.get(sourceInfo.name);
|
|
482
|
-
if (typeof info === 'undefined') {
|
|
483
|
-
throw Error(`Unable to find project info for ${sourceInfo.name}, please rebuild the project`);
|
|
484
|
-
}
|
|
485
|
-
const warnings = info.warnings;
|
|
486
|
-
const artifactDir = sourceInfo.getArtifactPath(artifactsRootDir);
|
|
487
|
-
if (sourceInfo.type === SourceKind.Contract) {
|
|
488
|
-
const artifact = await Contract.fromArtifactFile(artifactDir, info.bytecodeDebugPatch, info.codeHashDebug, structs);
|
|
489
|
-
contracts.set(artifact.name, new Compiled(sourceInfo, artifact, warnings));
|
|
490
|
-
}
|
|
491
|
-
else if (sourceInfo.type === SourceKind.Script) {
|
|
492
|
-
const artifact = await Script.fromArtifactFile(artifactDir, info.bytecodeDebugPatch, structs);
|
|
493
|
-
scripts.set(artifact.name, new Compiled(sourceInfo, artifact, warnings));
|
|
494
|
-
}
|
|
495
|
-
}
|
|
496
|
-
return new Project(contractsRootDir, artifactsRootDir, sourceInfos, contracts, scripts, structs, errorOnWarnings, projectArtifact);
|
|
497
|
-
}
|
|
498
|
-
catch (error) {
|
|
499
|
-
console.log(`Failed to load artifacts, error: ${error}, try to re-compile contracts...`);
|
|
500
|
-
return Project.compile(projectArtifact.fullNodeVersion, provider, sourceInfos, projectRootDir, contractsRootDir, artifactsRootDir, errorOnWarnings, compilerOptions, sourceInfos);
|
|
501
|
-
}
|
|
502
|
-
}
|
|
503
|
-
static getImportSourcePath(projectRootDir, importPath) {
|
|
504
|
-
const parts = importPath.split('/');
|
|
505
|
-
if (parts.length > 1 && parts[0] === 'std') {
|
|
506
|
-
const currentDir = path.dirname(__filename);
|
|
507
|
-
return path.join(...[currentDir, '..', '..', '..', importPath]);
|
|
508
|
-
}
|
|
509
|
-
let moduleDir = projectRootDir;
|
|
510
|
-
while (true) {
|
|
511
|
-
const expectedPath = path.join(...[moduleDir, 'node_modules', importPath]);
|
|
512
|
-
if (fs_1.default.existsSync(expectedPath)) {
|
|
513
|
-
return expectedPath;
|
|
514
|
-
}
|
|
515
|
-
const oldModuleDir = moduleDir;
|
|
516
|
-
moduleDir = path.join(moduleDir, '..');
|
|
517
|
-
if (oldModuleDir === moduleDir) {
|
|
518
|
-
throw new Error(`Specified import file does not exist: ${importPath}`);
|
|
519
|
-
}
|
|
520
|
-
}
|
|
521
|
-
}
|
|
522
|
-
static async handleImports(projectRootDir, contractRootDir, sourceStr, importsCache) {
|
|
523
|
-
const localImportsCache = [];
|
|
524
|
-
const result = sourceStr.replace(Project.importRegex, (match) => {
|
|
525
|
-
localImportsCache.push(match);
|
|
526
|
-
return '';
|
|
527
|
-
});
|
|
528
|
-
const externalSourceInfos = [];
|
|
529
|
-
for (const myImport of localImportsCache) {
|
|
530
|
-
const originImportPath = myImport.slice(8, -1);
|
|
531
|
-
const importPath = originImportPath.endsWith('.ral') ? originImportPath : originImportPath + '.ral';
|
|
532
|
-
if (!importsCache.includes(importPath)) {
|
|
533
|
-
importsCache.push(importPath);
|
|
534
|
-
const sourcePath = Project.getImportSourcePath(projectRootDir, importPath);
|
|
535
|
-
const sourceInfos = await Project.loadSourceFile(projectRootDir, contractRootDir, sourcePath, importsCache, true);
|
|
536
|
-
externalSourceInfos.push(...sourceInfos);
|
|
537
|
-
}
|
|
538
|
-
}
|
|
539
|
-
return [result, externalSourceInfos];
|
|
540
|
-
}
|
|
541
|
-
static async loadSourceFile(projectRootDir, contractsRootDir, sourcePath, importsCache, isExternal) {
|
|
542
|
-
const contractRelativePath = path.relative(contractsRootDir, sourcePath);
|
|
543
|
-
if (!sourcePath.endsWith('.ral')) {
|
|
544
|
-
throw new Error(`Invalid filename: ${sourcePath}, smart contract file name should end with ".ral"`);
|
|
545
|
-
}
|
|
546
|
-
const sourceBuffer = await fs_2.promises.readFile(sourcePath);
|
|
547
|
-
const [sourceStr, externalSourceInfos] = await Project.handleImports(projectRootDir, contractsRootDir, sourceBuffer.toString(), importsCache);
|
|
548
|
-
if (sourceStr.match(new RegExp('^import "', 'mg')) !== null) {
|
|
549
|
-
throw new Error(`Invalid import statements, source: ${sourcePath}`);
|
|
550
|
-
}
|
|
551
|
-
const sourceInfos = externalSourceInfos;
|
|
552
|
-
for (const matcher of this.matchers) {
|
|
553
|
-
const results = sourceStr.matchAll(matcher.matcher);
|
|
554
|
-
for (const result of results) {
|
|
555
|
-
const sourceInfo = await SourceInfo.from(matcher.type, result[1], sourceStr, contractRelativePath, isExternal);
|
|
556
|
-
sourceInfos.push(sourceInfo);
|
|
557
|
-
}
|
|
558
|
-
}
|
|
559
|
-
return sourceInfos;
|
|
560
|
-
}
|
|
561
|
-
static async loadSourceFiles(projectRootDir, contractsRootDir) {
|
|
562
|
-
const importsCache = [];
|
|
563
|
-
const sourceInfos = [];
|
|
564
|
-
const loadDir = async function (dirPath) {
|
|
565
|
-
const dirents = await fs_2.promises.readdir(dirPath, { withFileTypes: true });
|
|
566
|
-
for (const dirent of dirents) {
|
|
567
|
-
if (dirent.isFile()) {
|
|
568
|
-
const sourcePath = path.join(dirPath, dirent.name);
|
|
569
|
-
const infos = await Project.loadSourceFile(projectRootDir, contractsRootDir, sourcePath, importsCache, false);
|
|
570
|
-
sourceInfos.push(...infos);
|
|
571
|
-
}
|
|
572
|
-
else {
|
|
573
|
-
const newPath = path.join(dirPath, dirent.name);
|
|
574
|
-
await loadDir(newPath);
|
|
575
|
-
}
|
|
576
|
-
}
|
|
577
|
-
};
|
|
578
|
-
await loadDir(contractsRootDir);
|
|
579
|
-
const contractAndScriptSize = sourceInfos.filter((f) => f.type === SourceKind.Contract || f.type === SourceKind.Script).length;
|
|
580
|
-
if (sourceInfos.length === 0 || contractAndScriptSize === 0) {
|
|
581
|
-
throw new Error('Project have no source files');
|
|
582
|
-
}
|
|
583
|
-
return sourceInfos.sort((a, b) => a.type - b.type);
|
|
584
|
-
}
|
|
585
|
-
static async build(compilerOptionsPartial = {}, projectRootDir = '.', contractsRootDir = Project.DEFAULT_CONTRACTS_DIR, artifactsRootDir = Project.DEFAULT_ARTIFACTS_DIR, defaultFullNodeVersion = undefined, skipSaveArtifacts = false) {
|
|
586
|
-
const provider = (0, global_1.getCurrentNodeProvider)();
|
|
587
|
-
const fullNodeVersion = defaultFullNodeVersion ?? (await provider.infos.getInfosVersion()).version;
|
|
588
|
-
const sourceFiles = await Project.loadSourceFiles(projectRootDir, contractsRootDir);
|
|
589
|
-
const { errorOnWarnings, ...nodeCompilerOptions } = { ...exports.DEFAULT_COMPILER_OPTIONS, ...compilerOptionsPartial };
|
|
590
|
-
const projectArtifact = await ProjectArtifact.from(projectRootDir);
|
|
591
|
-
const changedSources = projectArtifact?.getChangedSources(sourceFiles) ?? sourceFiles;
|
|
592
|
-
if (projectArtifact === undefined ||
|
|
593
|
-
projectArtifact.needToReCompile(nodeCompilerOptions, fullNodeVersion) ||
|
|
594
|
-
changedSources.length > 0) {
|
|
595
|
-
if (fs_1.default.existsSync(artifactsRootDir)) {
|
|
596
|
-
removeOldArtifacts(artifactsRootDir, sourceFiles);
|
|
597
|
-
}
|
|
598
|
-
console.log(`Compiling contracts in folder "${contractsRootDir}"`);
|
|
599
|
-
Project.currentProject = await Project.compile(fullNodeVersion, provider, sourceFiles, projectRootDir, contractsRootDir, artifactsRootDir, errorOnWarnings, nodeCompilerOptions, changedSources, skipSaveArtifacts);
|
|
600
|
-
}
|
|
601
|
-
// we need to reload those contracts that did not regenerate bytecode
|
|
602
|
-
Project.currentProject = await Project.loadArtifacts(provider, sourceFiles, projectRootDir, contractsRootDir, artifactsRootDir, errorOnWarnings, nodeCompilerOptions);
|
|
603
|
-
}
|
|
604
|
-
}
|
|
605
|
-
exports.Project = Project;
|
|
606
|
-
Project.importRegex = new RegExp('^import "[^"./]+/[^"]*[a-z][a-z_0-9]*(.ral)?"', 'mg');
|
|
607
|
-
Project.abstractContractMatcher = new TypedMatcher('^Abstract Contract ([A-Z][a-zA-Z0-9]*)', SourceKind.AbstractContract);
|
|
608
|
-
Project.contractMatcher = new TypedMatcher('^Contract ([A-Z][a-zA-Z0-9]*)', SourceKind.Contract);
|
|
609
|
-
Project.interfaceMatcher = new TypedMatcher('^Interface ([A-Z][a-zA-Z0-9]*)', SourceKind.Interface);
|
|
610
|
-
Project.scriptMatcher = new TypedMatcher('^TxScript ([A-Z][a-zA-Z0-9]*)', SourceKind.Script);
|
|
611
|
-
Project.structMatcher = new TypedMatcher('struct ([A-Z][a-zA-Z0-9]*)', SourceKind.Struct);
|
|
612
|
-
Project.matchers = [
|
|
613
|
-
Project.abstractContractMatcher,
|
|
614
|
-
Project.contractMatcher,
|
|
615
|
-
Project.interfaceMatcher,
|
|
616
|
-
Project.scriptMatcher,
|
|
617
|
-
Project.structMatcher
|
|
618
|
-
];
|
|
619
|
-
Project.DEFAULT_CONTRACTS_DIR = 'contracts';
|
|
620
|
-
Project.DEFAULT_ARTIFACTS_DIR = 'artifacts';
|
|
621
92
|
class Artifact {
|
|
622
93
|
constructor(version, name, functions) {
|
|
623
94
|
this.version = version;
|
|
@@ -689,7 +160,7 @@ class Contract extends Artifact {
|
|
|
689
160
|
}
|
|
690
161
|
// support both 'code.ral' and 'code.ral.json'
|
|
691
162
|
static async fromArtifactFile(path, bytecodeDebugPatch, codeHashDebug, structs = []) {
|
|
692
|
-
const content = await
|
|
163
|
+
const content = await fs_1.promises.readFile(path);
|
|
693
164
|
const artifact = JSON.parse(content.toString());
|
|
694
165
|
return Contract.fromJson(artifact, bytecodeDebugPatch, codeHashDebug, structs);
|
|
695
166
|
}
|
|
@@ -810,9 +281,7 @@ class Contract extends Artifact {
|
|
|
810
281
|
};
|
|
811
282
|
}
|
|
812
283
|
static fromApiContractState(state, getContractByCodeHash) {
|
|
813
|
-
const contract = getContractByCodeHash
|
|
814
|
-
? getContractByCodeHash(state.codeHash)
|
|
815
|
-
: Project.currentProject.contractByCodeHash(state.codeHash);
|
|
284
|
+
const contract = getContractByCodeHash(state.codeHash);
|
|
816
285
|
return contract.fromApiContractState(state);
|
|
817
286
|
}
|
|
818
287
|
static fromApiEvent(event, codeHash, txId, getContractByCodeHash) {
|
|
@@ -827,9 +296,7 @@ class Contract extends Artifact {
|
|
|
827
296
|
name = Contract.ContractDestroyedEvent.name;
|
|
828
297
|
}
|
|
829
298
|
else {
|
|
830
|
-
const contract = getContractByCodeHash
|
|
831
|
-
? getContractByCodeHash(codeHash)
|
|
832
|
-
: Project.currentProject.contractByCodeHash(codeHash);
|
|
299
|
+
const contract = getContractByCodeHash(codeHash);
|
|
833
300
|
const eventSig = contract.eventsSig[event.eventIndex];
|
|
834
301
|
fields = fromApiEventFields(event.fields, eventSig);
|
|
835
302
|
name = eventSig.name;
|
|
@@ -843,7 +310,7 @@ class Contract extends Artifact {
|
|
|
843
310
|
fields: fields
|
|
844
311
|
};
|
|
845
312
|
}
|
|
846
|
-
fromApiTestContractResult(methodName, result, txId) {
|
|
313
|
+
fromApiTestContractResult(methodName, result, txId, getContractByCodeHash) {
|
|
847
314
|
const methodIndex = this.functions.findIndex((sig) => sig.name === methodName);
|
|
848
315
|
const returnTypes = this.functions[`${methodIndex}`].returnTypes;
|
|
849
316
|
const rawReturn = fromApiArray(result.returns, returnTypes, this.structs);
|
|
@@ -856,9 +323,9 @@ class Contract extends Artifact {
|
|
|
856
323
|
contractAddress: result.address,
|
|
857
324
|
returns: returns,
|
|
858
325
|
gasUsed: result.gasUsed,
|
|
859
|
-
contracts: result.contracts.map((contract) => Contract.fromApiContractState(contract)),
|
|
326
|
+
contracts: result.contracts.map((contract) => Contract.fromApiContractState(contract, getContractByCodeHash)),
|
|
860
327
|
txOutputs: result.txOutputs.map(fromApiOutput),
|
|
861
|
-
events: Contract.fromApiEvents(result.events, addressToCodeHash, txId),
|
|
328
|
+
events: Contract.fromApiEvents(result.events, addressToCodeHash, txId, getContractByCodeHash),
|
|
862
329
|
debugMessages: result.debugMessages
|
|
863
330
|
};
|
|
864
331
|
}
|
|
@@ -965,7 +432,7 @@ class Script extends Artifact {
|
|
|
965
432
|
return new Script(artifact.version, artifact.name, artifact.bytecodeTemplate, bytecodeDebugPatch, artifact.fieldsSig, artifact.functions, structs);
|
|
966
433
|
}
|
|
967
434
|
static async fromArtifactFile(path, bytecodeDebugPatch, structs = []) {
|
|
968
|
-
const content = await
|
|
435
|
+
const content = await fs_1.promises.readFile(path);
|
|
969
436
|
const artifact = JSON.parse(content.toString());
|
|
970
437
|
return this.fromJson(artifact, bytecodeDebugPatch, structs);
|
|
971
438
|
}
|
|
@@ -1341,7 +808,7 @@ function mapsToExistingContracts(contract, parentContractId, group, initialMaps)
|
|
|
1341
808
|
});
|
|
1342
809
|
return contractStates;
|
|
1343
810
|
}
|
|
1344
|
-
async function testMethod(factory, methodName, params) {
|
|
811
|
+
async function testMethod(factory, methodName, params, getContractByCodeHash) {
|
|
1345
812
|
const txId = params?.txId ?? randomTxId();
|
|
1346
813
|
const contract = factory.contract;
|
|
1347
814
|
const address = params.address ?? (0, utils_1.addressFromContractId)((0, utils_1.binToHex)(crypto.getRandomValues(new Uint8Array(32))));
|
|
@@ -1359,7 +826,7 @@ async function testMethod(factory, methodName, params) {
|
|
|
1359
826
|
});
|
|
1360
827
|
const apiResult = await (0, global_1.getCurrentNodeProvider)().contracts.postContractsTestContract(apiParams);
|
|
1361
828
|
const maps = existingContractsToMaps(contract, address, group, apiResult, initialMaps);
|
|
1362
|
-
const testResult = contract.fromApiTestContractResult(methodName, apiResult, txId);
|
|
829
|
+
const testResult = contract.fromApiTestContractResult(methodName, apiResult, txId, getContractByCodeHash);
|
|
1363
830
|
contract.printDebugMessages(methodName, testResult.debugMessages);
|
|
1364
831
|
return {
|
|
1365
832
|
...testResult,
|
|
@@ -33,3 +33,4 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
33
33
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
34
34
|
__exportStar(require("./status"), exports);
|
|
35
35
|
__exportStar(require("./sign-verify"), exports);
|
|
36
|
+
__exportStar(require("./utils"), exports);
|