@alephium/web3 0.2.0-test.0 → 0.2.0-test.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/contracts/add/add.ral +5 -8
- package/contracts/greeter/greeter.ral +3 -3
- package/contracts/greeter/greeter_interface.ral +1 -0
- package/contracts/greeter_main.ral +3 -5
- package/contracts/main.ral +0 -2
- package/contracts/sub/sub.ral +2 -1
- package/contracts/test/metadata.ral +18 -0
- package/contracts/test/warnings.ral +8 -0
- package/dist/alephium-web3.min.js +1 -1
- package/dist/alephium-web3.min.js.map +1 -1
- package/dist/scripts/create-project.js +2 -1
- package/dist/src/api/api-alephium.d.ts +37 -7
- package/dist/src/api/api-alephium.js +19 -3
- package/dist/src/api/api-explorer.d.ts +16 -0
- package/dist/src/api/api-explorer.js +26 -0
- package/dist/src/contract/contract.d.ts +86 -52
- package/dist/src/contract/contract.js +325 -218
- package/dist/src/global.d.ts +3 -0
- package/dist/src/global.js +38 -0
- package/dist/src/index.d.ts +1 -0
- package/dist/src/index.js +1 -0
- package/dist/src/signer/node-wallet.d.ts +1 -3
- package/dist/src/signer/node-wallet.js +2 -5
- package/dist/src/signer/signer.d.ts +1 -1
- package/dist/src/signer/signer.js +3 -2
- package/dist/src/test/index.d.ts +1 -2
- package/dist/src/test/index.js +4 -4
- package/dist/src/test/privatekey-wallet.d.ts +2 -3
- package/dist/src/test/privatekey-wallet.js +4 -4
- package/dist/src/utils/subscription.d.ts +0 -1
- package/dist/src/utils/subscription.js +2 -1
- package/dist/src/utils/utils.d.ts +2 -2
- package/dist/src/utils/utils.js +2 -2
- package/gitignore +0 -1
- package/package.json +3 -5
- package/scripts/create-project.ts +2 -1
- package/src/api/api-alephium.ts +57 -8
- package/src/api/api-explorer.ts +30 -0
- package/src/contract/contract.ts +430 -317
- package/src/contract/events.ts +2 -2
- package/src/contract/ralph.test.ts +4 -4
- package/src/global.ts +36 -0
- package/src/index.ts +1 -0
- package/src/signer/node-wallet.ts +2 -11
- package/src/signer/signer.ts +4 -3
- package/src/test/index.ts +2 -3
- package/src/test/privatekey-wallet.ts +4 -5
- package/src/transaction/status.ts +1 -1
- package/src/utils/subscription.ts +3 -3
- package/src/utils/utils.test.ts +1 -1
- package/src/utils/utils.ts +4 -4
- package/templates/base/package.json +2 -2
- package/templates/base/src/greeter.ts +8 -7
- package/templates/react/package.json +2 -2
- package/templates/react/src/App.tsx +2 -2
- package/test/contract.test.ts +60 -25
- package/test/events.test.ts +20 -17
- package/test/transaction.test.ts +10 -9
package/src/contract/contract.ts
CHANGED
|
@@ -21,246 +21,438 @@ import * as cryptojs from 'crypto-js'
|
|
|
21
21
|
import * as crypto from 'crypto'
|
|
22
22
|
import fs from 'fs'
|
|
23
23
|
import { promises as fsPromises } from 'fs'
|
|
24
|
-
import { NodeProvider } from '../api'
|
|
25
|
-
import { node } from '../api'
|
|
24
|
+
import { node, NodeProvider } from '../api'
|
|
26
25
|
import { SignDeployContractTxParams, SignExecuteScriptTxParams, SignerWithNodeProvider } from '../signer'
|
|
27
26
|
import * as ralph from './ralph'
|
|
28
27
|
import { bs58, binToHex, contractIdFromAddress, assertType, Eq } from '../utils'
|
|
28
|
+
import { CompileContractResult, CompileScriptResult } from '../api/api-alephium'
|
|
29
|
+
import { getCurrentNodeProvider } from '../global'
|
|
30
|
+
|
|
31
|
+
type FieldsSig = node.FieldsSig
|
|
32
|
+
type EventSig = node.EventSig
|
|
33
|
+
type FunctionSig = node.FunctionSig
|
|
34
|
+
|
|
35
|
+
enum SourceType {
|
|
36
|
+
Contract = 0,
|
|
37
|
+
Script = 1,
|
|
38
|
+
AbstractContract = 2,
|
|
39
|
+
Interface = 3
|
|
40
|
+
}
|
|
29
41
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
42
|
+
export type CompilerOptions = {
|
|
43
|
+
errorOnWarnings: boolean
|
|
44
|
+
ignoreUnusedConstantsWarnings: boolean
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export const DEFAULT_COMPILER_OPTIONS: CompilerOptions = {
|
|
48
|
+
errorOnWarnings: true,
|
|
49
|
+
ignoreUnusedConstantsWarnings: true
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
class TypedMatcher<T extends SourceType> {
|
|
53
|
+
matcher: RegExp
|
|
54
|
+
type: T
|
|
55
|
+
name: string | undefined
|
|
56
|
+
|
|
57
|
+
constructor(pattern: string, type: T) {
|
|
58
|
+
this.matcher = new RegExp(pattern, 'mg')
|
|
59
|
+
this.type = type
|
|
60
|
+
this.name = undefined
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
match(str: string): number {
|
|
64
|
+
const results = [...str.matchAll(this.matcher)]
|
|
65
|
+
if (results.length > 0) {
|
|
66
|
+
this.name = results[0][1]
|
|
45
67
|
}
|
|
68
|
+
return results.length
|
|
46
69
|
}
|
|
47
70
|
}
|
|
48
71
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
72
|
+
class SourceFile {
|
|
73
|
+
type: SourceType
|
|
74
|
+
typeId: string
|
|
75
|
+
contractPath: string
|
|
76
|
+
sourceCode: string
|
|
77
|
+
sourceCodeHash: string
|
|
78
|
+
|
|
79
|
+
getArtifactPath(artifactsRootPath: string): string {
|
|
80
|
+
return artifactsRootPath + this.contractPath.slice(this.contractPath.indexOf('/')) + '.json'
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
constructor(type: SourceType, typeId: string, sourceCode: string, contractPath: string) {
|
|
84
|
+
this.type = type
|
|
85
|
+
this.typeId = typeId
|
|
86
|
+
this.sourceCode = sourceCode
|
|
87
|
+
this.sourceCodeHash = cryptojs.SHA256(sourceCode).toString()
|
|
88
|
+
this.contractPath = contractPath
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
class Compiled<T extends Artifact> {
|
|
93
|
+
sourceFile: SourceFile
|
|
94
|
+
artifact: T
|
|
95
|
+
warnings: string[]
|
|
96
|
+
|
|
97
|
+
constructor(sourceFile: SourceFile, artifact: T, warnings: string[]) {
|
|
98
|
+
this.sourceFile = sourceFile
|
|
99
|
+
this.artifact = artifact
|
|
100
|
+
this.warnings = warnings
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
class ProjectArtifact {
|
|
105
|
+
static readonly artifactFileName = '.project.json'
|
|
106
|
+
|
|
107
|
+
infos: Map<string, { sourceCodeHash: string; warnings: string[] }>
|
|
108
|
+
|
|
109
|
+
constructor(infos: Map<string, { sourceCodeHash: string; warnings: string[] }>) {
|
|
110
|
+
this.infos = infos
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
async saveToFile(rootPath: string): Promise<void> {
|
|
114
|
+
const filepath = rootPath + '/' + ProjectArtifact.artifactFileName
|
|
115
|
+
const content = JSON.stringify(Object.fromEntries(this.infos), null, 2)
|
|
116
|
+
return fsPromises.writeFile(filepath, content)
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
sourceHasChanged(files: SourceFile[]): boolean {
|
|
120
|
+
if (files.length !== this.infos.size) {
|
|
121
|
+
return true
|
|
122
|
+
}
|
|
123
|
+
for (const file of files) {
|
|
124
|
+
const info = this.infos.get(file.contractPath)
|
|
125
|
+
if (typeof info === 'undefined' || info.sourceCodeHash !== file.sourceCodeHash) {
|
|
126
|
+
return true
|
|
68
127
|
}
|
|
69
|
-
this._artifactCache.set(contract.codeHash, contract)
|
|
70
128
|
}
|
|
129
|
+
return false
|
|
71
130
|
}
|
|
72
131
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
132
|
+
static async from(rootPath: string): Promise<ProjectArtifact | undefined> {
|
|
133
|
+
const filepath = rootPath + '/' + ProjectArtifact.artifactFileName
|
|
134
|
+
if (!fs.existsSync(filepath)) {
|
|
135
|
+
return undefined
|
|
136
|
+
}
|
|
137
|
+
const content = await fsPromises.readFile(filepath)
|
|
138
|
+
const files = new Map(
|
|
139
|
+
Object.entries<{ sourceCodeHash: string; warnings: string[] }>(JSON.parse(content.toString()))
|
|
140
|
+
)
|
|
141
|
+
return new ProjectArtifact(files)
|
|
76
142
|
}
|
|
143
|
+
}
|
|
77
144
|
|
|
78
|
-
|
|
79
|
-
|
|
145
|
+
export class Project {
|
|
146
|
+
sourceFiles: SourceFile[]
|
|
147
|
+
contracts: Compiled<Contract>[]
|
|
148
|
+
scripts: Compiled<Script>[]
|
|
149
|
+
|
|
150
|
+
readonly contractsRootPath: string
|
|
151
|
+
readonly artifactsRootPath: string
|
|
152
|
+
readonly nodeProvider: NodeProvider
|
|
153
|
+
|
|
154
|
+
static currentProject: Project
|
|
155
|
+
|
|
156
|
+
static readonly abstractContractMatcher = new TypedMatcher<SourceType>(
|
|
157
|
+
'^Abstract Contract ([A-Z][a-zA-Z0-9]*)\\(*',
|
|
158
|
+
SourceType.AbstractContract
|
|
159
|
+
)
|
|
160
|
+
static readonly contractMatcher = new TypedMatcher('^Contract ([A-Z][a-zA-Z0-9]*)\\(*', SourceType.Contract)
|
|
161
|
+
static readonly interfaceMatcher = new TypedMatcher('^Interface ([A-Z][a-zA-Z0-9]*) \\{', SourceType.Interface)
|
|
162
|
+
static readonly scriptMatcher = new TypedMatcher('^TxScript ([A-Z][a-zA-Z0-9]*)( \\{*|\\(*)', SourceType.Script)
|
|
163
|
+
static readonly matchers = [
|
|
164
|
+
Project.abstractContractMatcher,
|
|
165
|
+
Project.contractMatcher,
|
|
166
|
+
Project.interfaceMatcher,
|
|
167
|
+
Project.scriptMatcher
|
|
168
|
+
]
|
|
169
|
+
|
|
170
|
+
private constructor(
|
|
171
|
+
provider: NodeProvider,
|
|
172
|
+
contractsRootPath: string,
|
|
173
|
+
artifactsRootPath: string,
|
|
174
|
+
sourceFiles: SourceFile[],
|
|
175
|
+
contracts: Compiled<Contract>[],
|
|
176
|
+
scripts: Compiled<Script>[]
|
|
177
|
+
) {
|
|
178
|
+
this.nodeProvider = provider
|
|
179
|
+
this.contractsRootPath = contractsRootPath
|
|
180
|
+
this.artifactsRootPath = artifactsRootPath
|
|
181
|
+
this.sourceFiles = sourceFiles
|
|
182
|
+
this.contracts = contracts
|
|
183
|
+
this.scripts = scripts
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
private getContractPath(path: string): string {
|
|
187
|
+
return path.startsWith(`./${this.contractsRootPath}`)
|
|
188
|
+
? path.slice(2)
|
|
189
|
+
: path.startsWith(this.contractsRootPath)
|
|
190
|
+
? path
|
|
191
|
+
: this.contractsRootPath + '/' + path
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
private static checkCompilerWarnings(warnings: string[], compilerOptions: CompilerOptions): void {
|
|
195
|
+
const remains = compilerOptions.ignoreUnusedConstantsWarnings
|
|
196
|
+
? warnings.filter((s) => !s.includes('unused constants'))
|
|
197
|
+
: warnings
|
|
198
|
+
if (remains.length !== 0) {
|
|
199
|
+
const prefixPerWarning = ' - '
|
|
200
|
+
const warningString = prefixPerWarning + remains.join('\n' + prefixPerWarning)
|
|
201
|
+
const output = 'Compilation warnings:\n' + warningString + '\n'
|
|
202
|
+
if (compilerOptions.errorOnWarnings) {
|
|
203
|
+
throw new Error(output)
|
|
204
|
+
} else {
|
|
205
|
+
console.log(output)
|
|
206
|
+
}
|
|
207
|
+
}
|
|
80
208
|
}
|
|
81
209
|
|
|
82
|
-
static
|
|
83
|
-
const
|
|
84
|
-
const
|
|
85
|
-
if (
|
|
86
|
-
|
|
210
|
+
static contract(path: string, compilerOptions?: Partial<CompilerOptions>): Contract {
|
|
211
|
+
const contractPath = Project.currentProject.getContractPath(path)
|
|
212
|
+
const contract = Project.currentProject.contracts.find((c) => c.sourceFile.contractPath === contractPath)
|
|
213
|
+
if (typeof contract === 'undefined') {
|
|
214
|
+
throw new Error(`Contract ${contractPath} does not exist`)
|
|
87
215
|
}
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
216
|
+
Project.checkCompilerWarnings(contract.warnings, { ...DEFAULT_COMPILER_OPTIONS, ...compilerOptions })
|
|
217
|
+
return contract.artifact
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
static script(path: string, compilerOptions?: Partial<CompilerOptions>): Script {
|
|
221
|
+
const contractPath = Project.currentProject.getContractPath(path)
|
|
222
|
+
const script = Project.currentProject.scripts.find((c) => c.sourceFile.contractPath === contractPath)
|
|
223
|
+
if (typeof script === 'undefined') {
|
|
224
|
+
throw new Error(`Script ${contractPath} does not exist`)
|
|
225
|
+
}
|
|
226
|
+
Project.checkCompilerWarnings(script.warnings, { ...DEFAULT_COMPILER_OPTIONS, ...compilerOptions })
|
|
227
|
+
return script.artifact
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
private async saveArtifactsToFile(): Promise<void> {
|
|
231
|
+
const artifactsRootPath = this.artifactsRootPath
|
|
232
|
+
const saveToFile = async function (compiled: Compiled<Artifact>): Promise<void> {
|
|
233
|
+
const artifactPath = compiled.sourceFile.getArtifactPath(artifactsRootPath)
|
|
234
|
+
const folder = artifactPath.slice(0, artifactPath.lastIndexOf('/'))
|
|
235
|
+
if (!fs.existsSync(folder)) {
|
|
236
|
+
fs.mkdirSync(folder, { recursive: true })
|
|
103
237
|
}
|
|
238
|
+
return fsPromises.writeFile(artifactPath, compiled.artifact.toString())
|
|
239
|
+
}
|
|
240
|
+
for (const contract of this.contracts) {
|
|
241
|
+
await saveToFile(contract)
|
|
242
|
+
}
|
|
243
|
+
for (const script of this.scripts) {
|
|
244
|
+
await saveToFile(script)
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
contractByCodeHash(codeHash: string): Contract {
|
|
249
|
+
const contract = this.contracts.find((c) => c.artifact.codeHash === codeHash)
|
|
250
|
+
if (typeof contract === 'undefined') {
|
|
251
|
+
throw new Error(`Unknown code with code hash: ${codeHash}`)
|
|
252
|
+
}
|
|
253
|
+
return contract.artifact
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
private async saveProjectArtifactToFile(): Promise<void> {
|
|
257
|
+
const files: Map<string, { sourceCodeHash: string; warnings: string[] }> = new Map()
|
|
258
|
+
this.contracts.forEach((c) => {
|
|
259
|
+
files.set(c.sourceFile.contractPath, {
|
|
260
|
+
sourceCodeHash: c.sourceFile.sourceCodeHash,
|
|
261
|
+
warnings: c.warnings
|
|
262
|
+
})
|
|
104
263
|
})
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
contractStr: string,
|
|
111
|
-
importsCache: string[]
|
|
112
|
-
): Promise<string> {
|
|
113
|
-
const localImportsCache: string[] = []
|
|
114
|
-
let result = contractStr.replace(Common.importRegex, (match) => {
|
|
115
|
-
localImportsCache.push(match)
|
|
116
|
-
return ''
|
|
264
|
+
this.scripts.forEach((s) => {
|
|
265
|
+
files.set(s.sourceFile.contractPath, {
|
|
266
|
+
sourceCodeHash: s.sourceFile.sourceCodeHash,
|
|
267
|
+
warnings: s.warnings
|
|
268
|
+
})
|
|
117
269
|
})
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
return result
|
|
270
|
+
const compiledSize = this.contracts.length + this.scripts.length
|
|
271
|
+
this.sourceFiles.slice(compiledSize).forEach((c) => {
|
|
272
|
+
files.set(c.contractPath, {
|
|
273
|
+
sourceCodeHash: c.sourceCodeHash,
|
|
274
|
+
warnings: []
|
|
275
|
+
})
|
|
276
|
+
})
|
|
277
|
+
const projectArtifact = new ProjectArtifact(files)
|
|
278
|
+
await projectArtifact.saveToFile(this.artifactsRootPath)
|
|
130
279
|
}
|
|
131
280
|
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
const
|
|
139
|
-
const
|
|
281
|
+
private static async compile(
|
|
282
|
+
provider: NodeProvider,
|
|
283
|
+
files: SourceFile[],
|
|
284
|
+
contractsRootPath: string,
|
|
285
|
+
artifactsRootPath: string
|
|
286
|
+
): Promise<Project> {
|
|
287
|
+
const sourceStr = files.map((f) => f.sourceCode).join('\n')
|
|
288
|
+
const result = await provider.contracts.postContractsCompileProject({
|
|
289
|
+
code: sourceStr
|
|
290
|
+
})
|
|
291
|
+
const contracts: Compiled<Contract>[] = []
|
|
292
|
+
const scripts: Compiled<Script>[] = []
|
|
293
|
+
result.contracts.forEach((contractResult, index) => {
|
|
294
|
+
const sourceFile = files[`${index}`]
|
|
295
|
+
const contract = Contract.fromCompileResult(sourceFile.typeId, contractResult)
|
|
296
|
+
contracts.push(new Compiled(sourceFile, contract, contractResult.warnings))
|
|
297
|
+
})
|
|
298
|
+
result.scripts.forEach((scriptResult, index) => {
|
|
299
|
+
const sourceFile = files[index + contracts.length]
|
|
300
|
+
const script = Script.fromCompileResult(sourceFile.typeId, scriptResult)
|
|
301
|
+
scripts.push(new Compiled(sourceFile, script, scriptResult.warnings))
|
|
302
|
+
})
|
|
303
|
+
const project = new Project(provider, contractsRootPath, artifactsRootPath, files, contracts, scripts)
|
|
304
|
+
await project.saveArtifactsToFile()
|
|
305
|
+
await project.saveProjectArtifactToFile()
|
|
306
|
+
return project
|
|
307
|
+
}
|
|
140
308
|
|
|
141
|
-
|
|
142
|
-
|
|
309
|
+
private static async loadArtifacts(
|
|
310
|
+
provider: NodeProvider,
|
|
311
|
+
files: SourceFile[],
|
|
312
|
+
projectArtifact: ProjectArtifact,
|
|
313
|
+
contractsRootPath: string,
|
|
314
|
+
artifactsRootPath: string
|
|
315
|
+
): Promise<Project> {
|
|
316
|
+
try {
|
|
317
|
+
const contracts: Compiled<Contract>[] = []
|
|
318
|
+
const scripts: Compiled<Script>[] = []
|
|
319
|
+
for (const file of files) {
|
|
320
|
+
const info = projectArtifact.infos.get(file.contractPath)
|
|
321
|
+
if (typeof info === 'undefined') {
|
|
322
|
+
throw Error(`Unable to find project info for ${file.contractPath}, please rebuild the project`)
|
|
323
|
+
}
|
|
324
|
+
const warnings = info.warnings
|
|
325
|
+
const artifactPath = file.getArtifactPath(artifactsRootPath)
|
|
326
|
+
if (file.type === SourceType.Contract) {
|
|
327
|
+
const artifact = await Contract.fromArtifactFile(artifactPath)
|
|
328
|
+
contracts.push(new Compiled(file, artifact, warnings))
|
|
329
|
+
} else if (file.type === SourceType.Script) {
|
|
330
|
+
const artifact = await Script.fromArtifactFile(artifactPath)
|
|
331
|
+
scripts.push(new Compiled(file, artifact, warnings))
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
return new Project(provider, contractsRootPath, artifactsRootPath, files, contracts, scripts)
|
|
335
|
+
} catch (error) {
|
|
336
|
+
console.log(`Failed to load artifacts, error: ${error}, try to re-compile contracts...`)
|
|
337
|
+
return Project.compile(provider, files, contractsRootPath, artifactsRootPath)
|
|
338
|
+
}
|
|
143
339
|
}
|
|
144
340
|
|
|
145
|
-
static
|
|
146
|
-
|
|
147
|
-
|
|
341
|
+
private static async loadSourceFile(dirPath: string, filename: string): Promise<SourceFile> {
|
|
342
|
+
const contractPath = dirPath + '/' + filename
|
|
343
|
+
if (!filename.endsWith('.ral')) {
|
|
344
|
+
throw new Error(`Invalid filename: ${contractPath}, smart contract file name should end with ".ral"`)
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
const sourceBuffer = await fsPromises.readFile(contractPath)
|
|
348
|
+
const sourceStr = sourceBuffer.toString()
|
|
349
|
+
const results = this.matchers.map((m) => m.match(sourceStr))
|
|
350
|
+
const matchNumber = results.reduce((a, b) => a + b, 0)
|
|
351
|
+
if (matchNumber === 0) {
|
|
352
|
+
throw new Error(`No contract defined in file: ${contractPath}`)
|
|
353
|
+
}
|
|
354
|
+
if (matchNumber > 1) {
|
|
355
|
+
throw new Error(`Multiple definitions in file: ${contractPath}`)
|
|
356
|
+
}
|
|
357
|
+
const matcherIndex = results.indexOf(1)
|
|
358
|
+
const matcher = this.matchers[`${matcherIndex}`]
|
|
359
|
+
const type = matcher.type
|
|
360
|
+
if (matcher.name === undefined) {
|
|
361
|
+
throw new Error(`Invalid definition in file: ${contractPath}`)
|
|
362
|
+
}
|
|
363
|
+
return new SourceFile(type, matcher.name, sourceStr, contractPath)
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
private static async loadSourceFiles(contractsRootPath: string): Promise<SourceFile[]> {
|
|
367
|
+
const loadDir = async function (dirPath: string, results: SourceFile[]): Promise<void> {
|
|
368
|
+
const dirents = await fsPromises.readdir(dirPath, { withFileTypes: true })
|
|
369
|
+
for (const dirent of dirents) {
|
|
370
|
+
if (dirent.isFile()) {
|
|
371
|
+
const file = await Project.loadSourceFile(dirPath, dirent.name)
|
|
372
|
+
results.push(file)
|
|
373
|
+
} else {
|
|
374
|
+
const newPath = dirPath + '/' + dirent.name
|
|
375
|
+
await loadDir(newPath, results)
|
|
376
|
+
}
|
|
377
|
+
}
|
|
148
378
|
}
|
|
379
|
+
const sourceFiles: SourceFile[] = []
|
|
380
|
+
await loadDir(contractsRootPath, sourceFiles)
|
|
381
|
+
const contractAndScriptSize = sourceFiles.filter(
|
|
382
|
+
(f) => f.type === SourceType.Contract || f.type === SourceType.Script
|
|
383
|
+
).length
|
|
384
|
+
if (sourceFiles.length === 0 || contractAndScriptSize === 0) {
|
|
385
|
+
throw new Error('Project have no source files')
|
|
386
|
+
}
|
|
387
|
+
return sourceFiles.sort((a, b) => a.type - b.type)
|
|
149
388
|
}
|
|
150
389
|
|
|
151
|
-
|
|
152
|
-
provider
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
Common.checkFileNameExtension(sourceFile.contractPath)
|
|
158
|
-
|
|
159
|
-
const contractStr = await loadContractStr(sourceFile, [])
|
|
160
|
-
const contractHash = cryptojs.SHA256(contractStr).toString()
|
|
161
|
-
const existingContract = this._getArtifactFromCache(contractHash)
|
|
162
|
-
if (typeof existingContract !== 'undefined') {
|
|
163
|
-
return existingContract as unknown as T
|
|
390
|
+
static async build(contractsRootPath = 'contracts', artifactsRootPath = 'artifacts'): Promise<void> {
|
|
391
|
+
const provider = getCurrentNodeProvider()
|
|
392
|
+
const sourceFiles = await Project.loadSourceFiles(contractsRootPath)
|
|
393
|
+
const projectArtifact = await ProjectArtifact.from(artifactsRootPath)
|
|
394
|
+
if (typeof projectArtifact === 'undefined' || projectArtifact.sourceHasChanged(sourceFiles)) {
|
|
395
|
+
Project.currentProject = await Project.compile(provider, sourceFiles, contractsRootPath, artifactsRootPath)
|
|
164
396
|
} else {
|
|
165
|
-
|
|
397
|
+
Project.currentProject = await Project.loadArtifacts(
|
|
398
|
+
provider,
|
|
399
|
+
sourceFiles,
|
|
400
|
+
projectArtifact,
|
|
401
|
+
contractsRootPath,
|
|
402
|
+
artifactsRootPath
|
|
403
|
+
)
|
|
166
404
|
}
|
|
167
405
|
}
|
|
406
|
+
}
|
|
168
407
|
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
408
|
+
export abstract class Artifact {
|
|
409
|
+
readonly typeId: string
|
|
410
|
+
readonly functions: FunctionSig[]
|
|
411
|
+
|
|
412
|
+
constructor(typeId: string, functions: FunctionSig[]) {
|
|
413
|
+
this.typeId = typeId
|
|
414
|
+
this.functions = functions
|
|
175
415
|
}
|
|
176
416
|
|
|
177
417
|
abstract buildByteCodeToDeploy(initialFields?: Fields): string
|
|
418
|
+
|
|
419
|
+
publicFunctions(): string[] {
|
|
420
|
+
return this.functions.filter((func) => func.isPublic).map((func) => func.name)
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
usingPreapprovedAssetsFunctions(): string[] {
|
|
424
|
+
return this.functions.filter((func) => func.usePreapprovedAssets).map((func) => func.name)
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
usingAssetsInContractFunctions(): string[] {
|
|
428
|
+
return this.functions.filter((func) => func.useAssetsInContract).map((func) => func.name)
|
|
429
|
+
}
|
|
178
430
|
}
|
|
179
431
|
|
|
180
|
-
export class Contract extends
|
|
432
|
+
export class Contract extends Artifact {
|
|
181
433
|
readonly bytecode: string
|
|
182
434
|
readonly codeHash: string
|
|
183
|
-
readonly fieldsSig:
|
|
184
|
-
readonly eventsSig:
|
|
435
|
+
readonly fieldsSig: FieldsSig
|
|
436
|
+
readonly eventsSig: EventSig[]
|
|
185
437
|
|
|
186
438
|
constructor(
|
|
187
|
-
|
|
439
|
+
typeId: string,
|
|
188
440
|
bytecode: string,
|
|
189
441
|
codeHash: string,
|
|
190
|
-
fieldsSig:
|
|
191
|
-
eventsSig:
|
|
192
|
-
functions:
|
|
442
|
+
fieldsSig: FieldsSig,
|
|
443
|
+
eventsSig: EventSig[],
|
|
444
|
+
functions: FunctionSig[]
|
|
193
445
|
) {
|
|
194
|
-
super(
|
|
446
|
+
super(typeId, functions)
|
|
195
447
|
this.bytecode = bytecode
|
|
196
448
|
this.codeHash = codeHash
|
|
197
449
|
this.fieldsSig = fieldsSig
|
|
198
450
|
this.eventsSig = eventsSig
|
|
199
451
|
}
|
|
200
452
|
|
|
201
|
-
static checkCodeType(fileName: string, contractStr: string): void {
|
|
202
|
-
const interfaceMatches = contractStr.match(Contract.interfaceRegex)
|
|
203
|
-
const contractMatches = contractStr.match(Contract.contractRegex)
|
|
204
|
-
if (interfaceMatches === null && contractMatches === null) {
|
|
205
|
-
throw new Error(`No contract found in: ${fileName}`)
|
|
206
|
-
}
|
|
207
|
-
if (interfaceMatches && contractMatches) {
|
|
208
|
-
throw new Error(`Multiple contracts and interfaces in: ${fileName}`)
|
|
209
|
-
}
|
|
210
|
-
if (interfaceMatches === null) {
|
|
211
|
-
if (contractMatches !== null && contractMatches.length > 1) {
|
|
212
|
-
throw new Error(`Multiple contracts in: ${fileName}`)
|
|
213
|
-
}
|
|
214
|
-
}
|
|
215
|
-
if (contractMatches === null) {
|
|
216
|
-
if (interfaceMatches !== null && interfaceMatches.length > 1) {
|
|
217
|
-
throw new Error(`Multiple interfaces in: ${fileName}`)
|
|
218
|
-
}
|
|
219
|
-
}
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
private static async loadContractStr(sourceFile: SourceFile): Promise<string> {
|
|
223
|
-
return Common._loadContractStr(sourceFile, [], (code) => Contract.checkCodeType(sourceFile.contractPath, code))
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
static async fromSource(provider: NodeProvider, path: string): Promise<Contract> {
|
|
227
|
-
if (!fs.existsSync(Common._artifactsFolder())) {
|
|
228
|
-
fs.mkdirSync(Common._artifactsFolder(), { recursive: true })
|
|
229
|
-
}
|
|
230
|
-
const sourceFile = this.getSourceFile(path, [])
|
|
231
|
-
const contract = await Common._from(
|
|
232
|
-
provider,
|
|
233
|
-
sourceFile,
|
|
234
|
-
(sourceFile) => Contract.loadContractStr(sourceFile),
|
|
235
|
-
Contract.compile
|
|
236
|
-
)
|
|
237
|
-
this._putArtifactToCache(contract)
|
|
238
|
-
return contract
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
private static async compile(
|
|
242
|
-
provider: NodeProvider,
|
|
243
|
-
sourceFile: SourceFile,
|
|
244
|
-
contractStr: string,
|
|
245
|
-
contractHash: string
|
|
246
|
-
): Promise<Contract> {
|
|
247
|
-
const compiled = await provider.contracts.postContractsCompileContract({ code: contractStr })
|
|
248
|
-
const artifact = new Contract(
|
|
249
|
-
contractHash,
|
|
250
|
-
compiled.bytecode,
|
|
251
|
-
compiled.codeHash,
|
|
252
|
-
compiled.fields,
|
|
253
|
-
compiled.events,
|
|
254
|
-
compiled.functions
|
|
255
|
-
)
|
|
256
|
-
await artifact._saveToFile(sourceFile)
|
|
257
|
-
return artifact
|
|
258
|
-
}
|
|
259
|
-
|
|
260
453
|
// TODO: safely parse json
|
|
261
454
|
static fromJson(artifact: any): Contract {
|
|
262
455
|
if (
|
|
263
|
-
artifact.sourceCodeSha256 == null ||
|
|
264
456
|
artifact.bytecode == null ||
|
|
265
457
|
artifact.codeHash == null ||
|
|
266
458
|
artifact.fieldsSig == null ||
|
|
@@ -270,44 +462,44 @@ export class Contract extends Common {
|
|
|
270
462
|
throw Error('The artifact JSON for contract is incomplete')
|
|
271
463
|
}
|
|
272
464
|
const contract = new Contract(
|
|
273
|
-
artifact.
|
|
465
|
+
artifact.typeId,
|
|
274
466
|
artifact.bytecode,
|
|
275
467
|
artifact.codeHash,
|
|
276
468
|
artifact.fieldsSig,
|
|
277
469
|
artifact.eventsSig,
|
|
278
470
|
artifact.functions
|
|
279
471
|
)
|
|
280
|
-
this._putArtifactToCache(contract)
|
|
281
472
|
return contract
|
|
282
473
|
}
|
|
283
474
|
|
|
475
|
+
static fromCompileResult(typeId: string, result: CompileContractResult): Contract {
|
|
476
|
+
return new Contract(typeId, result.bytecode, result.codeHash, result.fields, result.events, result.functions)
|
|
477
|
+
}
|
|
478
|
+
|
|
284
479
|
// support both 'code.ral' and 'code.ral.json'
|
|
285
480
|
static async fromArtifactFile(path: string): Promise<Contract> {
|
|
286
|
-
const
|
|
287
|
-
const artifactPath = sourceFile.artifactPath
|
|
288
|
-
const content = await fsPromises.readFile(artifactPath)
|
|
481
|
+
const content = await fsPromises.readFile(path)
|
|
289
482
|
const artifact = JSON.parse(content.toString())
|
|
290
483
|
return Contract.fromJson(artifact)
|
|
291
484
|
}
|
|
292
485
|
|
|
293
|
-
async fetchState(
|
|
294
|
-
const state = await
|
|
486
|
+
async fetchState(address: string, group: number): Promise<ContractState> {
|
|
487
|
+
const state = await Project.currentProject.nodeProvider.contracts.getContractsAddressState(address, {
|
|
488
|
+
group: group
|
|
489
|
+
})
|
|
295
490
|
return this.fromApiContractState(state)
|
|
296
491
|
}
|
|
297
492
|
|
|
298
493
|
override toString(): string {
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
null,
|
|
309
|
-
2
|
|
310
|
-
)
|
|
494
|
+
const object = {
|
|
495
|
+
typeId: this.typeId,
|
|
496
|
+
bytecode: this.bytecode,
|
|
497
|
+
codeHash: this.codeHash,
|
|
498
|
+
fieldsSig: this.fieldsSig,
|
|
499
|
+
eventsSig: this.eventsSig,
|
|
500
|
+
functions: this.functions
|
|
501
|
+
}
|
|
502
|
+
return JSON.stringify(object, null, 2)
|
|
311
503
|
}
|
|
312
504
|
|
|
313
505
|
toState(fields: Fields, asset: Asset, address?: string): ContractState {
|
|
@@ -330,18 +522,17 @@ export class Contract extends Common {
|
|
|
330
522
|
}
|
|
331
523
|
|
|
332
524
|
private async _test(
|
|
333
|
-
provider: NodeProvider,
|
|
334
525
|
funcName: string,
|
|
335
526
|
params: TestContractParams,
|
|
336
527
|
expectPublic: boolean,
|
|
337
528
|
accessType: string
|
|
338
529
|
): Promise<TestContractResult> {
|
|
339
530
|
const apiParams: node.TestContract = this.toTestContract(funcName, params)
|
|
340
|
-
const apiResult = await
|
|
531
|
+
const apiResult = await Project.currentProject.nodeProvider.contracts.postContractsTestContract(apiParams)
|
|
341
532
|
|
|
342
533
|
const methodIndex =
|
|
343
534
|
typeof params.testMethodIndex !== 'undefined' ? params.testMethodIndex : this.getMethodIndex(funcName)
|
|
344
|
-
const isPublic = this.functions[`${methodIndex}`].
|
|
535
|
+
const isPublic = this.functions[`${methodIndex}`].isPublic
|
|
345
536
|
if (isPublic === expectPublic) {
|
|
346
537
|
const result = await this.fromTestContractResult(methodIndex, apiResult)
|
|
347
538
|
return result
|
|
@@ -350,20 +541,12 @@ export class Contract extends Common {
|
|
|
350
541
|
}
|
|
351
542
|
}
|
|
352
543
|
|
|
353
|
-
async testPublicMethod(
|
|
354
|
-
|
|
355
|
-
funcName: string,
|
|
356
|
-
params: TestContractParams
|
|
357
|
-
): Promise<TestContractResult> {
|
|
358
|
-
return this._test(provider, funcName, params, true, 'public')
|
|
544
|
+
async testPublicMethod(funcName: string, params: TestContractParams): Promise<TestContractResult> {
|
|
545
|
+
return this._test(funcName, params, true, 'public')
|
|
359
546
|
}
|
|
360
547
|
|
|
361
|
-
async testPrivateMethod(
|
|
362
|
-
|
|
363
|
-
funcName: string,
|
|
364
|
-
params: TestContractParams
|
|
365
|
-
): Promise<TestContractResult> {
|
|
366
|
-
return this._test(provider, funcName, params, false, 'private')
|
|
548
|
+
async testPrivateMethod(funcName: string, params: TestContractParams): Promise<TestContractResult> {
|
|
549
|
+
return this._test(funcName, params, false, 'private')
|
|
367
550
|
}
|
|
368
551
|
|
|
369
552
|
toApiFields(fields?: Fields): node.Val[] {
|
|
@@ -409,33 +592,8 @@ export class Contract extends Common {
|
|
|
409
592
|
}
|
|
410
593
|
}
|
|
411
594
|
|
|
412
|
-
static async fromCodeHash(codeHash: string): Promise<Contract> {
|
|
413
|
-
const cached = this._getArtifactFromCache(codeHash)
|
|
414
|
-
if (typeof cached !== 'undefined') {
|
|
415
|
-
return cached as Contract
|
|
416
|
-
}
|
|
417
|
-
|
|
418
|
-
const files = await fsPromises.readdir(Common._artifactsFolder())
|
|
419
|
-
for (const file of files) {
|
|
420
|
-
if (file.endsWith('.ral.json')) {
|
|
421
|
-
try {
|
|
422
|
-
const contract = await Contract.fromArtifactFile(file)
|
|
423
|
-
if (contract.codeHash === codeHash) {
|
|
424
|
-
return contract as Contract
|
|
425
|
-
}
|
|
426
|
-
} catch (_) {}
|
|
427
|
-
}
|
|
428
|
-
}
|
|
429
|
-
|
|
430
|
-
throw new Error(`Unknown code with code hash: ${codeHash}`)
|
|
431
|
-
}
|
|
432
|
-
|
|
433
|
-
static async getFieldsSig(state: node.ContractState): Promise<node.FieldsSig> {
|
|
434
|
-
return Contract.fromCodeHash(state.codeHash).then((contract) => contract.fieldsSig)
|
|
435
|
-
}
|
|
436
|
-
|
|
437
595
|
async fromApiContractState(state: node.ContractState): Promise<ContractState> {
|
|
438
|
-
const contract =
|
|
596
|
+
const contract = Project.currentProject.contractByCodeHash(state.codeHash)
|
|
439
597
|
return {
|
|
440
598
|
address: state.address,
|
|
441
599
|
contractId: binToHex(contractIdFromAddress(state.address)),
|
|
@@ -443,21 +601,19 @@ export class Contract extends Common {
|
|
|
443
601
|
initialStateHash: state.initialStateHash,
|
|
444
602
|
codeHash: state.codeHash,
|
|
445
603
|
fields: fromApiFields(state.fields, contract.fieldsSig),
|
|
446
|
-
fieldsSig:
|
|
604
|
+
fieldsSig: contract.fieldsSig,
|
|
447
605
|
asset: fromApiAsset(state.asset)
|
|
448
606
|
}
|
|
449
607
|
}
|
|
450
608
|
|
|
451
|
-
static ContractCreatedEvent:
|
|
609
|
+
static ContractCreatedEvent: EventSig = {
|
|
452
610
|
name: 'ContractCreated',
|
|
453
|
-
signature: 'event ContractCreated(address:Address)',
|
|
454
611
|
fieldNames: ['address'],
|
|
455
612
|
fieldTypes: ['Address']
|
|
456
613
|
}
|
|
457
614
|
|
|
458
|
-
static ContractDestroyedEvent:
|
|
615
|
+
static ContractDestroyedEvent: EventSig = {
|
|
459
616
|
name: 'ContractDestroyed',
|
|
460
|
-
signature: 'event ContractDestroyed(address:Address)',
|
|
461
617
|
fieldNames: ['address'],
|
|
462
618
|
fieldTypes: ['Address']
|
|
463
619
|
}
|
|
@@ -466,14 +622,14 @@ export class Contract extends Common {
|
|
|
466
622
|
event: node.ContractEventByTxId,
|
|
467
623
|
codeHash: string | undefined
|
|
468
624
|
): Promise<ContractEventByTxId> {
|
|
469
|
-
let eventSig:
|
|
625
|
+
let eventSig: EventSig
|
|
470
626
|
|
|
471
627
|
if (event.eventIndex == -1) {
|
|
472
628
|
eventSig = this.ContractCreatedEvent
|
|
473
629
|
} else if (event.eventIndex == -2) {
|
|
474
630
|
eventSig = this.ContractDestroyedEvent
|
|
475
631
|
} else {
|
|
476
|
-
const contract =
|
|
632
|
+
const contract = Project.currentProject.contractByCodeHash(codeHash!)
|
|
477
633
|
eventSig = contract.eventsSig[event.eventIndex]
|
|
478
634
|
}
|
|
479
635
|
|
|
@@ -541,85 +697,42 @@ export class Contract extends Common {
|
|
|
541
697
|
}
|
|
542
698
|
}
|
|
543
699
|
|
|
544
|
-
export class Script extends
|
|
700
|
+
export class Script extends Artifact {
|
|
545
701
|
readonly bytecodeTemplate: string
|
|
546
|
-
readonly fieldsSig:
|
|
702
|
+
readonly fieldsSig: FieldsSig
|
|
547
703
|
|
|
548
|
-
constructor(
|
|
549
|
-
|
|
550
|
-
bytecodeTemplate: string,
|
|
551
|
-
fieldsSig: node.FieldsSig,
|
|
552
|
-
functions: node.FunctionSig[]
|
|
553
|
-
) {
|
|
554
|
-
super(sourceCodeSha256, functions)
|
|
704
|
+
constructor(typeId: string, bytecodeTemplate: string, fieldsSig: FieldsSig, functions: FunctionSig[]) {
|
|
705
|
+
super(typeId, functions)
|
|
555
706
|
this.bytecodeTemplate = bytecodeTemplate
|
|
556
707
|
this.fieldsSig = fieldsSig
|
|
557
708
|
}
|
|
558
709
|
|
|
559
|
-
static
|
|
560
|
-
|
|
561
|
-
if (scriptMatches === null) {
|
|
562
|
-
throw new Error(`No script found in: ${fileName}`)
|
|
563
|
-
} else if (scriptMatches.length > 1) {
|
|
564
|
-
throw new Error(`Multiple scripts in: ${fileName}`)
|
|
565
|
-
} else {
|
|
566
|
-
return
|
|
567
|
-
}
|
|
568
|
-
}
|
|
569
|
-
|
|
570
|
-
private static async loadContractStr(sourceFile: SourceFile): Promise<string> {
|
|
571
|
-
return Common._loadContractStr(sourceFile, [], (code) => Script.checkCodeType(sourceFile.contractPath, code))
|
|
572
|
-
}
|
|
573
|
-
|
|
574
|
-
static async fromSource(provider: NodeProvider, path: string): Promise<Script> {
|
|
575
|
-
const sourceFile = this.getSourceFile(path, [])
|
|
576
|
-
return Common._from(provider, sourceFile, (sourceFile) => Script.loadContractStr(sourceFile), Script.compile)
|
|
577
|
-
}
|
|
578
|
-
|
|
579
|
-
private static async compile(
|
|
580
|
-
provider: NodeProvider,
|
|
581
|
-
sourceFile: SourceFile,
|
|
582
|
-
scriptStr: string,
|
|
583
|
-
contractHash: string
|
|
584
|
-
): Promise<Script> {
|
|
585
|
-
const compiled = await provider.contracts.postContractsCompileScript({ code: scriptStr })
|
|
586
|
-
const artifact = new Script(contractHash, compiled.bytecodeTemplate, compiled.fields, compiled.functions)
|
|
587
|
-
await artifact._saveToFile(sourceFile)
|
|
588
|
-
return artifact
|
|
710
|
+
static fromCompileResult(typeId: string, result: CompileScriptResult): Script {
|
|
711
|
+
return new Script(typeId, result.bytecodeTemplate, result.fields, result.functions)
|
|
589
712
|
}
|
|
590
713
|
|
|
591
714
|
// TODO: safely parse json
|
|
592
715
|
static fromJson(artifact: any): Script {
|
|
593
|
-
if (
|
|
594
|
-
artifact.sourceCodeSha256 == null ||
|
|
595
|
-
artifact.bytecodeTemplate == null ||
|
|
596
|
-
artifact.fieldsSig == null ||
|
|
597
|
-
artifact.functions == null
|
|
598
|
-
) {
|
|
716
|
+
if (artifact.bytecodeTemplate == null || artifact.fieldsSig == null || artifact.functions == null) {
|
|
599
717
|
throw Error('The artifact JSON for script is incomplete')
|
|
600
718
|
}
|
|
601
|
-
return new Script(artifact.
|
|
719
|
+
return new Script(artifact.typeId, artifact.bytecodeTemplate, artifact.fieldsSig, artifact.functions)
|
|
602
720
|
}
|
|
603
721
|
|
|
604
722
|
static async fromArtifactFile(path: string): Promise<Script> {
|
|
605
|
-
const
|
|
606
|
-
const artifactPath = sourceFile.artifactPath
|
|
607
|
-
const content = await fsPromises.readFile(artifactPath)
|
|
723
|
+
const content = await fsPromises.readFile(path)
|
|
608
724
|
const artifact = JSON.parse(content.toString())
|
|
609
725
|
return this.fromJson(artifact)
|
|
610
726
|
}
|
|
611
727
|
|
|
612
728
|
override toString(): string {
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
null,
|
|
621
|
-
2
|
|
622
|
-
)
|
|
729
|
+
const object = {
|
|
730
|
+
typeId: this.typeId,
|
|
731
|
+
bytecodeTemplate: this.bytecodeTemplate,
|
|
732
|
+
fieldsSig: this.fieldsSig,
|
|
733
|
+
functions: this.functions
|
|
734
|
+
}
|
|
735
|
+
return JSON.stringify(object, null, 2)
|
|
623
736
|
}
|
|
624
737
|
|
|
625
738
|
async paramsForDeployment(params: BuildExecuteScriptTx): Promise<SignExecuteScriptTxParams> {
|
|
@@ -895,7 +1008,7 @@ export interface ContractState {
|
|
|
895
1008
|
initialStateHash?: string
|
|
896
1009
|
codeHash: string
|
|
897
1010
|
fields: Fields
|
|
898
|
-
fieldsSig:
|
|
1011
|
+
fieldsSig: FieldsSig
|
|
899
1012
|
asset: Asset
|
|
900
1013
|
}
|
|
901
1014
|
|
|
@@ -918,12 +1031,12 @@ function toApiContractState(state: ContractState): node.ContractState {
|
|
|
918
1031
|
}
|
|
919
1032
|
}
|
|
920
1033
|
|
|
921
|
-
function toApiFields(fields: Fields, fieldsSig:
|
|
1034
|
+
function toApiFields(fields: Fields, fieldsSig: FieldsSig): node.Val[] {
|
|
922
1035
|
return toApiVals(fields, fieldsSig.names, fieldsSig.types)
|
|
923
1036
|
}
|
|
924
1037
|
|
|
925
|
-
function toApiArgs(args: Arguments, funcSig:
|
|
926
|
-
return toApiVals(args, funcSig.
|
|
1038
|
+
function toApiArgs(args: Arguments, funcSig: FunctionSig): node.Val[] {
|
|
1039
|
+
return toApiVals(args, funcSig.paramNames, funcSig.paramTypes)
|
|
927
1040
|
}
|
|
928
1041
|
|
|
929
1042
|
function toApiVals(fields: Fields, names: string[], types: string[]): node.Val[] {
|