@alephium/web3 0.2.0-rc.5 → 0.2.0-rc.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.eslintignore +2 -2
- package/README.md +2 -135
- package/contracts/greeter/greeter.ral +1 -1
- package/dist/alephium-web3.min.js +1 -1
- package/dist/alephium-web3.min.js.LICENSE.txt +0 -17
- package/dist/alephium-web3.min.js.map +1 -1
- package/dist/scripts/create-project.js +1 -1
- package/dist/src/api/api-alephium.d.ts +19 -6
- package/dist/src/api/api-explorer.d.ts +16 -16
- package/dist/src/api/index.js +5 -1
- package/dist/src/contract/contract.d.ts +30 -8
- package/dist/src/contract/contract.js +105 -58
- package/dist/src/contract/index.js +5 -1
- package/dist/src/global.d.ts +3 -0
- package/{src/utils/djb2.test.ts → dist/src/global.js} +20 -17
- package/dist/src/index.d.ts +2 -0
- package/dist/src/index.js +20 -1
- package/dist/src/signer/index.d.ts +0 -1
- package/dist/src/signer/index.js +5 -2
- package/dist/src/signer/signer.d.ts +1 -1
- package/dist/src/signer/signer.js +8 -3
- package/dist/src/transaction/index.d.ts +0 -1
- package/dist/src/transaction/index.js +5 -2
- package/dist/src/utils/index.d.ts +0 -1
- package/dist/src/utils/index.js +5 -2
- package/dist/src/utils/subscription.d.ts +0 -1
- package/dist/src/utils/subscription.js +2 -1
- package/dist/src/utils/utils.d.ts +3 -2
- package/dist/src/utils/utils.js +16 -15
- package/jest-config.json +11 -0
- package/package.json +6 -32
- package/scripts/create-project.ts +1 -1
- package/src/api/api-alephium.ts +14 -0
- package/src/contract/contract.ts +161 -65
- package/src/{test/index.ts → global.ts} +14 -10
- package/src/index.ts +3 -0
- package/src/signer/index.ts +0 -1
- package/src/signer/signer.ts +3 -2
- package/src/transaction/index.ts +0 -1
- package/src/utils/index.ts +0 -1
- package/src/utils/subscription.ts +2 -2
- package/src/utils/utils.ts +7 -7
- 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/.eslintrc.json +0 -21
- package/LICENSE +0 -165
- package/contracts/add/add.ral +0 -15
- package/contracts/main.ral +0 -4
- package/contracts/sub/sub.ral +0 -10
- package/contracts/test/metadata.ral +0 -18
- package/contracts/test/warnings.ral +0 -8
- package/dist/src/signer/node-wallet.d.ts +0 -13
- package/dist/src/signer/node-wallet.js +0 -60
- package/dist/src/test/index.d.ts +0 -7
- package/dist/src/test/index.js +0 -41
- package/dist/src/test/privatekey-wallet.d.ts +0 -12
- package/dist/src/test/privatekey-wallet.js +0 -68
- package/dist/src/transaction/sign-verify.d.ts +0 -2
- package/dist/src/transaction/sign-verify.js +0 -58
- package/dist/src/utils/password-crypto.d.ts +0 -2
- package/dist/src/utils/password-crypto.js +0 -69
- package/gitignore +0 -9
- package/src/contract/ralph.test.ts +0 -178
- package/src/fixtures/address.json +0 -36
- package/src/fixtures/balance.json +0 -9
- package/src/fixtures/self-clique.json +0 -19
- package/src/fixtures/transaction.json +0 -13
- package/src/fixtures/transactions.json +0 -179
- package/src/signer/fixtures/genesis.json +0 -26
- package/src/signer/fixtures/wallets.json +0 -26
- package/src/signer/node-wallet.ts +0 -74
- package/src/test/privatekey-wallet.ts +0 -58
- package/src/transaction/sign-verify.test.ts +0 -50
- package/src/transaction/sign-verify.ts +0 -39
- package/src/utils/address.test.ts +0 -47
- package/src/utils/password-crypto.test.ts +0 -27
- package/src/utils/password-crypto.ts +0 -77
- package/src/utils/utils.test.ts +0 -161
- package/test/contract.test.ts +0 -213
- package/test/events.test.ts +0 -143
- package/test/transaction.test.ts +0 -74
package/src/contract/contract.ts
CHANGED
|
@@ -17,16 +17,15 @@ along with the library. If not, see <http://www.gnu.org/licenses/>.
|
|
|
17
17
|
*/
|
|
18
18
|
|
|
19
19
|
import { Buffer } from 'buffer/'
|
|
20
|
-
import
|
|
21
|
-
import * as crypto from 'crypto'
|
|
20
|
+
import { webcrypto as crypto } from 'crypto'
|
|
22
21
|
import fs from 'fs'
|
|
23
22
|
import { promises as fsPromises } from 'fs'
|
|
24
|
-
import { NodeProvider } from '../api'
|
|
25
|
-
import { node } from '../api'
|
|
23
|
+
import { node, NodeProvider } from '../api'
|
|
26
24
|
import { SignDeployContractTxParams, SignExecuteScriptTxParams, SignerWithNodeProvider } from '../signer'
|
|
27
25
|
import * as ralph from './ralph'
|
|
28
26
|
import { bs58, binToHex, contractIdFromAddress, assertType, Eq } from '../utils'
|
|
29
27
|
import { CompileContractResult, CompileScriptResult } from '../api/api-alephium'
|
|
28
|
+
import { getCurrentNodeProvider } from '../global'
|
|
30
29
|
|
|
31
30
|
type FieldsSig = node.FieldsSig
|
|
32
31
|
type EventSig = node.EventSig
|
|
@@ -39,6 +38,21 @@ enum SourceType {
|
|
|
39
38
|
Interface = 3
|
|
40
39
|
}
|
|
41
40
|
|
|
41
|
+
export type CompilerOptions = node.CompilerOptions & {
|
|
42
|
+
errorOnWarnings: boolean
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export const DEFAULT_NODE_COMPILER_OPTIONS: node.CompilerOptions = {
|
|
46
|
+
ignoreUnusedConstantsWarnings: false,
|
|
47
|
+
ignoreUnusedVariablesWarnings: false,
|
|
48
|
+
ignoreUnusedFieldsWarnings: false,
|
|
49
|
+
ignoreUnusedPrivateFunctionsWarnings: false,
|
|
50
|
+
ignoreReadonlyCheckWarnings: false,
|
|
51
|
+
ignoreExternalCallCheckWarnings: false
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export const DEFAULT_COMPILER_OPTIONS: CompilerOptions = { errorOnWarnings: true, ...DEFAULT_NODE_COMPILER_OPTIONS }
|
|
55
|
+
|
|
42
56
|
class TypedMatcher<T extends SourceType> {
|
|
43
57
|
matcher: RegExp
|
|
44
58
|
type: T
|
|
@@ -64,12 +78,17 @@ class SourceFile {
|
|
|
64
78
|
return artifactsRootPath + this.contractPath.slice(this.contractPath.indexOf('/')) + '.json'
|
|
65
79
|
}
|
|
66
80
|
|
|
67
|
-
constructor(type: SourceType, sourceCode: string, contractPath: string) {
|
|
81
|
+
constructor(type: SourceType, sourceCode: string, sourceCodeHash: string, contractPath: string) {
|
|
68
82
|
this.type = type
|
|
69
83
|
this.sourceCode = sourceCode
|
|
70
|
-
this.sourceCodeHash =
|
|
84
|
+
this.sourceCodeHash = sourceCodeHash
|
|
71
85
|
this.contractPath = contractPath
|
|
72
86
|
}
|
|
87
|
+
|
|
88
|
+
static async from(type: SourceType, sourceCode: string, contractPath: string): Promise<SourceFile> {
|
|
89
|
+
const sourceCodeHash = await crypto.subtle.digest('SHA-256', Buffer.from(sourceCode))
|
|
90
|
+
return new SourceFile(type, sourceCode, Buffer.from(sourceCodeHash).toString('hex'), contractPath)
|
|
91
|
+
}
|
|
73
92
|
}
|
|
74
93
|
|
|
75
94
|
class Compiled<T extends Artifact> {
|
|
@@ -87,19 +106,47 @@ class Compiled<T extends Artifact> {
|
|
|
87
106
|
class ProjectArtifact {
|
|
88
107
|
static readonly artifactFileName = '.project.json'
|
|
89
108
|
|
|
109
|
+
compilerOptionsUsed: node.CompilerOptions
|
|
90
110
|
infos: Map<string, { sourceCodeHash: string; warnings: string[] }>
|
|
91
111
|
|
|
92
|
-
|
|
112
|
+
static checkCompilerOptionsParameter(compilerOptions: node.CompilerOptions): void {
|
|
113
|
+
if (Object.keys(compilerOptions).length != Object.keys(DEFAULT_NODE_COMPILER_OPTIONS).length) {
|
|
114
|
+
throw Error(`Not all compiler options are set: ${compilerOptions}`)
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
const combined = { ...compilerOptions, ...DEFAULT_NODE_COMPILER_OPTIONS }
|
|
118
|
+
if (Object.keys(combined).length !== Object.keys(DEFAULT_NODE_COMPILER_OPTIONS).length) {
|
|
119
|
+
throw Error(`There are unknown compiler options: ${compilerOptions}`)
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
constructor(
|
|
124
|
+
compilerOptionsUsed: node.CompilerOptions,
|
|
125
|
+
infos: Map<string, { sourceCodeHash: string; warnings: string[] }>
|
|
126
|
+
) {
|
|
127
|
+
ProjectArtifact.checkCompilerOptionsParameter(compilerOptionsUsed)
|
|
128
|
+
this.compilerOptionsUsed = compilerOptionsUsed
|
|
93
129
|
this.infos = infos
|
|
94
130
|
}
|
|
95
131
|
|
|
96
132
|
async saveToFile(rootPath: string): Promise<void> {
|
|
97
133
|
const filepath = rootPath + '/' + ProjectArtifact.artifactFileName
|
|
98
|
-
const
|
|
134
|
+
const artifact = { compilerOptionsUsed: this.compilerOptionsUsed, infos: Object.fromEntries(this.infos) }
|
|
135
|
+
const content = JSON.stringify(artifact, null, 2)
|
|
99
136
|
return fsPromises.writeFile(filepath, content)
|
|
100
137
|
}
|
|
101
138
|
|
|
102
|
-
|
|
139
|
+
needToReCompile(compilerOptions: node.CompilerOptions, files: SourceFile[]): boolean {
|
|
140
|
+
ProjectArtifact.checkCompilerOptionsParameter(compilerOptions)
|
|
141
|
+
|
|
142
|
+
const optionsMatched = Object.entries(compilerOptions).every(([key, inputOption]) => {
|
|
143
|
+
const usedOption = this.compilerOptionsUsed[`${key}`]
|
|
144
|
+
return usedOption === inputOption
|
|
145
|
+
})
|
|
146
|
+
if (!optionsMatched) {
|
|
147
|
+
return true
|
|
148
|
+
}
|
|
149
|
+
|
|
103
150
|
if (files.length !== this.infos.size) {
|
|
104
151
|
return true
|
|
105
152
|
}
|
|
@@ -109,6 +156,7 @@ class ProjectArtifact {
|
|
|
109
156
|
return true
|
|
110
157
|
}
|
|
111
158
|
}
|
|
159
|
+
|
|
112
160
|
return false
|
|
113
161
|
}
|
|
114
162
|
|
|
@@ -118,10 +166,10 @@ class ProjectArtifact {
|
|
|
118
166
|
return undefined
|
|
119
167
|
}
|
|
120
168
|
const content = await fsPromises.readFile(filepath)
|
|
121
|
-
const
|
|
122
|
-
|
|
123
|
-
)
|
|
124
|
-
return new ProjectArtifact(files)
|
|
169
|
+
const json = JSON.parse(content.toString())
|
|
170
|
+
const compilerOptionsUsed = json.compilerOptionsUsed as node.CompilerOptions
|
|
171
|
+
const files = new Map(Object.entries<{ sourceCodeHash: string; warnings: string[] }>(json.infos))
|
|
172
|
+
return new ProjectArtifact(compilerOptionsUsed, files)
|
|
125
173
|
}
|
|
126
174
|
}
|
|
127
175
|
|
|
@@ -129,6 +177,7 @@ export class Project {
|
|
|
129
177
|
sourceFiles: SourceFile[]
|
|
130
178
|
contracts: Compiled<Contract>[]
|
|
131
179
|
scripts: Compiled<Script>[]
|
|
180
|
+
projectArtifact: ProjectArtifact
|
|
132
181
|
|
|
133
182
|
readonly contractsRootPath: string
|
|
134
183
|
readonly artifactsRootPath: string
|
|
@@ -150,13 +199,44 @@ export class Project {
|
|
|
150
199
|
Project.scriptMatcher
|
|
151
200
|
]
|
|
152
201
|
|
|
202
|
+
static buildProjectArtifact(
|
|
203
|
+
sourceFiles: SourceFile[],
|
|
204
|
+
contracts: Compiled<Contract>[],
|
|
205
|
+
scripts: Compiled<Script>[],
|
|
206
|
+
compilerOptions: node.CompilerOptions
|
|
207
|
+
): ProjectArtifact {
|
|
208
|
+
const files: Map<string, { sourceCodeHash: string; warnings: string[] }> = new Map()
|
|
209
|
+
contracts.forEach((c) => {
|
|
210
|
+
files.set(c.sourceFile.contractPath, {
|
|
211
|
+
sourceCodeHash: c.sourceFile.sourceCodeHash,
|
|
212
|
+
warnings: c.warnings
|
|
213
|
+
})
|
|
214
|
+
})
|
|
215
|
+
scripts.forEach((s) => {
|
|
216
|
+
files.set(s.sourceFile.contractPath, {
|
|
217
|
+
sourceCodeHash: s.sourceFile.sourceCodeHash,
|
|
218
|
+
warnings: s.warnings
|
|
219
|
+
})
|
|
220
|
+
})
|
|
221
|
+
const compiledSize = contracts.length + scripts.length
|
|
222
|
+
sourceFiles.slice(compiledSize).forEach((c) => {
|
|
223
|
+
files.set(c.contractPath, {
|
|
224
|
+
sourceCodeHash: c.sourceCodeHash,
|
|
225
|
+
warnings: []
|
|
226
|
+
})
|
|
227
|
+
})
|
|
228
|
+
return new ProjectArtifact(compilerOptions, files)
|
|
229
|
+
}
|
|
230
|
+
|
|
153
231
|
private constructor(
|
|
154
232
|
provider: NodeProvider,
|
|
155
233
|
contractsRootPath: string,
|
|
156
234
|
artifactsRootPath: string,
|
|
157
235
|
sourceFiles: SourceFile[],
|
|
158
236
|
contracts: Compiled<Contract>[],
|
|
159
|
-
scripts: Compiled<Script>[]
|
|
237
|
+
scripts: Compiled<Script>[],
|
|
238
|
+
errorOnWarnings: boolean,
|
|
239
|
+
projectArtifact: ProjectArtifact
|
|
160
240
|
) {
|
|
161
241
|
this.nodeProvider = provider
|
|
162
242
|
this.contractsRootPath = contractsRootPath
|
|
@@ -164,6 +244,14 @@ export class Project {
|
|
|
164
244
|
this.sourceFiles = sourceFiles
|
|
165
245
|
this.contracts = contracts
|
|
166
246
|
this.scripts = scripts
|
|
247
|
+
this.projectArtifact = projectArtifact
|
|
248
|
+
|
|
249
|
+
if (errorOnWarnings) {
|
|
250
|
+
Project.checkCompilerWarnings(
|
|
251
|
+
[...contracts.map((c) => c.warnings).flat(), ...scripts.map((s) => s.warnings).flat()],
|
|
252
|
+
errorOnWarnings
|
|
253
|
+
)
|
|
254
|
+
}
|
|
167
255
|
}
|
|
168
256
|
|
|
169
257
|
private getContractPath(path: string): string {
|
|
@@ -174,16 +262,11 @@ export class Project {
|
|
|
174
262
|
: this.contractsRootPath + '/' + path
|
|
175
263
|
}
|
|
176
264
|
|
|
177
|
-
|
|
178
|
-
warnings
|
|
179
|
-
errorOnWarnings: boolean,
|
|
180
|
-
ignoreUnusedConstantsWarnings: boolean
|
|
181
|
-
): void {
|
|
182
|
-
const remains = ignoreUnusedConstantsWarnings ? warnings.filter((s) => !s.includes('unused constants')) : warnings
|
|
183
|
-
if (remains.length !== 0) {
|
|
265
|
+
static checkCompilerWarnings(warnings: string[], errorOnWarnings: boolean): void {
|
|
266
|
+
if (warnings.length !== 0) {
|
|
184
267
|
const prefixPerWarning = ' - '
|
|
185
|
-
const warningString = prefixPerWarning +
|
|
186
|
-
const output =
|
|
268
|
+
const warningString = prefixPerWarning + warnings.join('\n' + prefixPerWarning)
|
|
269
|
+
const output = `Compilation warnings:\n` + warningString + '\n'
|
|
187
270
|
if (errorOnWarnings) {
|
|
188
271
|
throw new Error(output)
|
|
189
272
|
} else {
|
|
@@ -192,23 +275,21 @@ export class Project {
|
|
|
192
275
|
}
|
|
193
276
|
}
|
|
194
277
|
|
|
195
|
-
static contract(path: string
|
|
278
|
+
static contract(path: string): Contract {
|
|
196
279
|
const contractPath = Project.currentProject.getContractPath(path)
|
|
197
280
|
const contract = Project.currentProject.contracts.find((c) => c.sourceFile.contractPath === contractPath)
|
|
198
281
|
if (typeof contract === 'undefined') {
|
|
199
282
|
throw new Error(`Contract ${contractPath} does not exist`)
|
|
200
283
|
}
|
|
201
|
-
Project.checkCompilerWarnings(contract.warnings, errorOnWarnings, ignoreUnusedConstantsWarnings)
|
|
202
284
|
return contract.artifact
|
|
203
285
|
}
|
|
204
286
|
|
|
205
|
-
static script(path: string
|
|
287
|
+
static script(path: string): Script {
|
|
206
288
|
const contractPath = Project.currentProject.getContractPath(path)
|
|
207
289
|
const script = Project.currentProject.scripts.find((c) => c.sourceFile.contractPath === contractPath)
|
|
208
290
|
if (typeof script === 'undefined') {
|
|
209
291
|
throw new Error(`Script ${contractPath} does not exist`)
|
|
210
292
|
}
|
|
211
|
-
Project.checkCompilerWarnings(script.warnings, errorOnWarnings, ignoreUnusedConstantsWarnings)
|
|
212
293
|
return script.artifact
|
|
213
294
|
}
|
|
214
295
|
|
|
@@ -228,6 +309,7 @@ export class Project {
|
|
|
228
309
|
for (const script of this.scripts) {
|
|
229
310
|
await saveToFile(script)
|
|
230
311
|
}
|
|
312
|
+
await this.projectArtifact.saveToFile(this.artifactsRootPath)
|
|
231
313
|
}
|
|
232
314
|
|
|
233
315
|
contractByCodeHash(codeHash: string): Contract {
|
|
@@ -238,40 +320,18 @@ export class Project {
|
|
|
238
320
|
return contract.artifact
|
|
239
321
|
}
|
|
240
322
|
|
|
241
|
-
private async saveProjectArtifactToFile(): Promise<void> {
|
|
242
|
-
const files: Map<string, { sourceCodeHash: string; warnings: string[] }> = new Map()
|
|
243
|
-
this.contracts.forEach((c) => {
|
|
244
|
-
files.set(c.sourceFile.contractPath, {
|
|
245
|
-
sourceCodeHash: c.sourceFile.sourceCodeHash,
|
|
246
|
-
warnings: c.warnings
|
|
247
|
-
})
|
|
248
|
-
})
|
|
249
|
-
this.scripts.forEach((s) => {
|
|
250
|
-
files.set(s.sourceFile.contractPath, {
|
|
251
|
-
sourceCodeHash: s.sourceFile.sourceCodeHash,
|
|
252
|
-
warnings: s.warnings
|
|
253
|
-
})
|
|
254
|
-
})
|
|
255
|
-
const compiledSize = this.contracts.length + this.scripts.length
|
|
256
|
-
this.sourceFiles.slice(compiledSize).forEach((c) => {
|
|
257
|
-
files.set(c.contractPath, {
|
|
258
|
-
sourceCodeHash: c.sourceCodeHash,
|
|
259
|
-
warnings: []
|
|
260
|
-
})
|
|
261
|
-
})
|
|
262
|
-
const projectArtifact = new ProjectArtifact(files)
|
|
263
|
-
await projectArtifact.saveToFile(this.artifactsRootPath)
|
|
264
|
-
}
|
|
265
|
-
|
|
266
323
|
private static async compile(
|
|
267
324
|
provider: NodeProvider,
|
|
268
325
|
files: SourceFile[],
|
|
269
326
|
contractsRootPath: string,
|
|
270
|
-
artifactsRootPath: string
|
|
327
|
+
artifactsRootPath: string,
|
|
328
|
+
errorOnWarnings: boolean,
|
|
329
|
+
compilerOptions: node.CompilerOptions
|
|
271
330
|
): Promise<Project> {
|
|
272
331
|
const sourceStr = files.map((f) => f.sourceCode).join('\n')
|
|
273
332
|
const result = await provider.contracts.postContractsCompileProject({
|
|
274
|
-
code: sourceStr
|
|
333
|
+
code: sourceStr,
|
|
334
|
+
compilerOptions: compilerOptions
|
|
275
335
|
})
|
|
276
336
|
const contracts: Compiled<Contract>[] = []
|
|
277
337
|
const scripts: Compiled<Script>[] = []
|
|
@@ -285,9 +345,18 @@ export class Project {
|
|
|
285
345
|
const script = Script.fromCompileResult(scriptResult)
|
|
286
346
|
scripts.push(new Compiled(sourceFile, script, scriptResult.warnings))
|
|
287
347
|
})
|
|
288
|
-
const
|
|
348
|
+
const projectArtifact = Project.buildProjectArtifact(files, contracts, scripts, compilerOptions)
|
|
349
|
+
const project = new Project(
|
|
350
|
+
provider,
|
|
351
|
+
contractsRootPath,
|
|
352
|
+
artifactsRootPath,
|
|
353
|
+
files,
|
|
354
|
+
contracts,
|
|
355
|
+
scripts,
|
|
356
|
+
errorOnWarnings,
|
|
357
|
+
projectArtifact
|
|
358
|
+
)
|
|
289
359
|
await project.saveArtifactsToFile()
|
|
290
|
-
await project.saveProjectArtifactToFile()
|
|
291
360
|
return project
|
|
292
361
|
}
|
|
293
362
|
|
|
@@ -296,7 +365,9 @@ export class Project {
|
|
|
296
365
|
files: SourceFile[],
|
|
297
366
|
projectArtifact: ProjectArtifact,
|
|
298
367
|
contractsRootPath: string,
|
|
299
|
-
artifactsRootPath: string
|
|
368
|
+
artifactsRootPath: string,
|
|
369
|
+
errorOnWarnings: boolean,
|
|
370
|
+
compilerOptions: node.CompilerOptions
|
|
300
371
|
): Promise<Project> {
|
|
301
372
|
try {
|
|
302
373
|
const contracts: Compiled<Contract>[] = []
|
|
@@ -316,10 +387,20 @@ export class Project {
|
|
|
316
387
|
scripts.push(new Compiled(file, artifact, warnings))
|
|
317
388
|
}
|
|
318
389
|
}
|
|
319
|
-
|
|
390
|
+
|
|
391
|
+
return new Project(
|
|
392
|
+
provider,
|
|
393
|
+
contractsRootPath,
|
|
394
|
+
artifactsRootPath,
|
|
395
|
+
files,
|
|
396
|
+
contracts,
|
|
397
|
+
scripts,
|
|
398
|
+
errorOnWarnings,
|
|
399
|
+
projectArtifact
|
|
400
|
+
)
|
|
320
401
|
} catch (error) {
|
|
321
402
|
console.log(`Failed to load artifacts, error: ${error}, try to re-compile contracts...`)
|
|
322
|
-
return Project.compile(provider, files, contractsRootPath, artifactsRootPath)
|
|
403
|
+
return Project.compile(provider, files, contractsRootPath, artifactsRootPath, errorOnWarnings, compilerOptions)
|
|
323
404
|
}
|
|
324
405
|
}
|
|
325
406
|
|
|
@@ -341,7 +422,7 @@ export class Project {
|
|
|
341
422
|
}
|
|
342
423
|
const matcherIndex = results.indexOf(1)
|
|
343
424
|
const type = this.matchers[`${matcherIndex}`].type
|
|
344
|
-
return
|
|
425
|
+
return SourceFile.from(type, sourceStr, contractPath)
|
|
345
426
|
}
|
|
346
427
|
|
|
347
428
|
private static async loadSourceFiles(contractsRootPath: string): Promise<SourceFile[]> {
|
|
@@ -369,21 +450,34 @@ export class Project {
|
|
|
369
450
|
}
|
|
370
451
|
|
|
371
452
|
static async build(
|
|
372
|
-
|
|
453
|
+
compilerOptionsPartial: Partial<CompilerOptions> = {},
|
|
373
454
|
contractsRootPath = 'contracts',
|
|
374
455
|
artifactsRootPath = 'artifacts'
|
|
375
456
|
): Promise<void> {
|
|
457
|
+
const provider = getCurrentNodeProvider()
|
|
376
458
|
const sourceFiles = await Project.loadSourceFiles(contractsRootPath)
|
|
459
|
+
const { errorOnWarnings, ...nodeCompilerOptions } = { ...DEFAULT_COMPILER_OPTIONS, ...compilerOptionsPartial }
|
|
377
460
|
const projectArtifact = await ProjectArtifact.from(artifactsRootPath)
|
|
378
|
-
if (typeof projectArtifact === 'undefined' || projectArtifact.
|
|
379
|
-
|
|
461
|
+
if (typeof projectArtifact === 'undefined' || projectArtifact.needToReCompile(nodeCompilerOptions, sourceFiles)) {
|
|
462
|
+
console.log(`Compile contracts in folder "${contractsRootPath}"`)
|
|
463
|
+
Project.currentProject = await Project.compile(
|
|
464
|
+
provider,
|
|
465
|
+
sourceFiles,
|
|
466
|
+
contractsRootPath,
|
|
467
|
+
artifactsRootPath,
|
|
468
|
+
errorOnWarnings,
|
|
469
|
+
nodeCompilerOptions
|
|
470
|
+
)
|
|
380
471
|
} else {
|
|
472
|
+
console.log(`Load compiled contracts from folder "${artifactsRootPath}"`)
|
|
381
473
|
Project.currentProject = await Project.loadArtifacts(
|
|
382
474
|
provider,
|
|
383
475
|
sourceFiles,
|
|
384
476
|
projectArtifact,
|
|
385
477
|
contractsRootPath,
|
|
386
|
-
artifactsRootPath
|
|
478
|
+
artifactsRootPath,
|
|
479
|
+
errorOnWarnings,
|
|
480
|
+
nodeCompilerOptions
|
|
387
481
|
)
|
|
388
482
|
}
|
|
389
483
|
}
|
|
@@ -494,8 +588,10 @@ export class Contract extends Artifact {
|
|
|
494
588
|
}
|
|
495
589
|
}
|
|
496
590
|
|
|
591
|
+
// no need to be cryptographically strong random
|
|
497
592
|
static randomAddress(): string {
|
|
498
|
-
const bytes =
|
|
593
|
+
const bytes = new Uint8Array(33)
|
|
594
|
+
crypto.getRandomValues(bytes)
|
|
499
595
|
bytes[0] = 3
|
|
500
596
|
return bs58.encode(bytes)
|
|
501
597
|
}
|
|
@@ -16,17 +16,21 @@ You should have received a copy of the GNU Lesser General Public License
|
|
|
16
16
|
along with the library. If not, see <http://www.gnu.org/licenses/>.
|
|
17
17
|
*/
|
|
18
18
|
|
|
19
|
-
import { NodeProvider } from '
|
|
20
|
-
import { NodeWallet } from '../signer'
|
|
19
|
+
import { NodeProvider } from './api'
|
|
21
20
|
|
|
22
|
-
|
|
23
|
-
export const testAddress = '1DrDyTr9RpRsQnDnXo2YRiPzPW4ooHX5LLoqXrqfMrpQH'
|
|
24
|
-
export const testPassword = 'alph'
|
|
21
|
+
let _currentNodeProvider: NodeProvider | undefined = undefined
|
|
25
22
|
|
|
26
|
-
export
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
23
|
+
export function setCurrentNodeProvider(provider: NodeProvider | string): void {
|
|
24
|
+
if (typeof provider == 'string') {
|
|
25
|
+
_currentNodeProvider = new NodeProvider(provider)
|
|
26
|
+
} else {
|
|
27
|
+
_currentNodeProvider = provider
|
|
28
|
+
}
|
|
30
29
|
}
|
|
31
30
|
|
|
32
|
-
export
|
|
31
|
+
export function getCurrentNodeProvider(): NodeProvider {
|
|
32
|
+
if (typeof _currentNodeProvider === 'undefined') {
|
|
33
|
+
throw Error('No node provider is set.')
|
|
34
|
+
}
|
|
35
|
+
return _currentNodeProvider
|
|
36
|
+
}
|
package/src/index.ts
CHANGED
package/src/signer/index.ts
CHANGED
package/src/signer/signer.ts
CHANGED
|
@@ -23,6 +23,7 @@ import * as utils from '../utils'
|
|
|
23
23
|
import { Eq, assertType } from '../utils'
|
|
24
24
|
import blake from 'blakejs'
|
|
25
25
|
import { Token } from '../api/api-alephium'
|
|
26
|
+
import { getCurrentNodeProvider } from '../global'
|
|
26
27
|
|
|
27
28
|
const ec = new EC('secp256k1')
|
|
28
29
|
|
|
@@ -167,8 +168,8 @@ export abstract class SignerWithNodeProvider implements SignerProvider {
|
|
|
167
168
|
}
|
|
168
169
|
}
|
|
169
170
|
|
|
170
|
-
constructor(
|
|
171
|
-
this.provider =
|
|
171
|
+
constructor(alwaysSubmitTx: boolean) {
|
|
172
|
+
this.provider = getCurrentNodeProvider()
|
|
172
173
|
this.alwaysSubmitTx = alwaysSubmitTx
|
|
173
174
|
}
|
|
174
175
|
|
package/src/transaction/index.ts
CHANGED
package/src/utils/index.ts
CHANGED
|
@@ -17,13 +17,13 @@ along with the library. If not, see <http://www.gnu.org/licenses/>.
|
|
|
17
17
|
*/
|
|
18
18
|
|
|
19
19
|
import EventEmitter from 'eventemitter3'
|
|
20
|
+
import { getCurrentNodeProvider } from '../global'
|
|
20
21
|
import { NodeProvider } from '../api'
|
|
21
22
|
|
|
22
23
|
type MessageCallback<Message> = (message: Message) => Promise<void>
|
|
23
24
|
type ErrorCallback<Message> = (error: any, subscription: Subscription<Message>) => Promise<void>
|
|
24
25
|
|
|
25
26
|
export interface SubscribeOptions<Message> {
|
|
26
|
-
provider: NodeProvider
|
|
27
27
|
pollingInterval: number
|
|
28
28
|
messageCallback: MessageCallback<Message>
|
|
29
29
|
errorCallback: ErrorCallback<Message>
|
|
@@ -40,7 +40,7 @@ export abstract class Subscription<Message> {
|
|
|
40
40
|
protected cancelled: boolean
|
|
41
41
|
|
|
42
42
|
constructor(options: SubscribeOptions<Message>) {
|
|
43
|
-
this.provider =
|
|
43
|
+
this.provider = getCurrentNodeProvider()
|
|
44
44
|
this.pollingInterval = options.pollingInterval
|
|
45
45
|
this.messageCallback = options.messageCallback
|
|
46
46
|
this.errorCallback = options.errorCallback
|
package/src/utils/utils.ts
CHANGED
|
@@ -51,7 +51,7 @@ export function signatureEncode(signature: EC.Signature): string {
|
|
|
51
51
|
}
|
|
52
52
|
|
|
53
53
|
// the signature should be in hex string format for 64 bytes
|
|
54
|
-
export
|
|
54
|
+
export function signatureDecode(ec: EC, signature: string): SignatureInput {
|
|
55
55
|
if (signature.length !== 128) {
|
|
56
56
|
throw new Error('Invalid signature length')
|
|
57
57
|
}
|
|
@@ -66,7 +66,7 @@ export const signatureDecode = (ec: EC, signature: string): SignatureInput => {
|
|
|
66
66
|
}
|
|
67
67
|
}
|
|
68
68
|
|
|
69
|
-
|
|
69
|
+
export function xorByte(intValue: number): number {
|
|
70
70
|
const byte0 = (intValue >> 24) & 0xff
|
|
71
71
|
const byte1 = (intValue >> 16) & 0xff
|
|
72
72
|
const byte2 = (intValue >> 8) & 0xff
|
|
@@ -85,7 +85,7 @@ enum AddressType {
|
|
|
85
85
|
P2C = 0x03
|
|
86
86
|
}
|
|
87
87
|
|
|
88
|
-
export
|
|
88
|
+
export function groupOfAddress(address: string): number {
|
|
89
89
|
const decoded = bs58.decode(address)
|
|
90
90
|
|
|
91
91
|
if (decoded.length == 0) throw new Error('Address string is empty')
|
|
@@ -103,7 +103,7 @@ export const groupOfAddress = (address: string): number => {
|
|
|
103
103
|
}
|
|
104
104
|
}
|
|
105
105
|
|
|
106
|
-
|
|
106
|
+
function groupOfAddressBytes(bytes: Uint8Array): number {
|
|
107
107
|
const hint = djb2(bytes) | 1
|
|
108
108
|
const hash = xorByte(hint)
|
|
109
109
|
const group = hash % TOTAL_NUMBER_OF_GROUPS
|
|
@@ -111,7 +111,7 @@ const groupOfAddressBytes = (bytes: Uint8Array): number => {
|
|
|
111
111
|
}
|
|
112
112
|
|
|
113
113
|
// Pay to public key hash address
|
|
114
|
-
|
|
114
|
+
function groupOfP2pkhAddress(address: Uint8Array): number {
|
|
115
115
|
if (address.length != 32) {
|
|
116
116
|
throw new Error(`Invalid p2pkh address length: ${address.length}`)
|
|
117
117
|
}
|
|
@@ -120,7 +120,7 @@ const groupOfP2pkhAddress = (address: Uint8Array): number => {
|
|
|
120
120
|
}
|
|
121
121
|
|
|
122
122
|
// Pay to multiple public key hash address
|
|
123
|
-
|
|
123
|
+
function groupOfP2mpkhAddress(address: Uint8Array): number {
|
|
124
124
|
if ((address.length - 2) % 32 != 0) {
|
|
125
125
|
throw new Error(`Invalid p2mpkh address length: ${address.length}`)
|
|
126
126
|
}
|
|
@@ -129,7 +129,7 @@ const groupOfP2mpkhAddress = (address: Uint8Array): number => {
|
|
|
129
129
|
}
|
|
130
130
|
|
|
131
131
|
// Pay to script hash address
|
|
132
|
-
|
|
132
|
+
function groupOfP2shAddress(address: Uint8Array): number {
|
|
133
133
|
return groupOfAddressBytes(address)
|
|
134
134
|
}
|
|
135
135
|
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"version": "0.1.0",
|
|
4
4
|
"license": "GPL",
|
|
5
5
|
"config": {
|
|
6
|
-
"alephium_version": "1.5.0-
|
|
6
|
+
"alephium_version": "1.5.0-rc7"
|
|
7
7
|
},
|
|
8
8
|
"scripts": {
|
|
9
9
|
"build": "rm -rf dist && npx tsc --build .",
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
"stop-devnet": "node scripts/stop-devnet.js"
|
|
13
13
|
},
|
|
14
14
|
"dependencies": {
|
|
15
|
-
"@alephium/web3": "0.2.0-rc.
|
|
15
|
+
"@alephium/web3": "0.2.0-rc.7"
|
|
16
16
|
},
|
|
17
17
|
"devDependencies": {
|
|
18
18
|
"@types/elliptic": "^6.4.13",
|
|
@@ -2,21 +2,22 @@
|
|
|
2
2
|
* greeter.ts
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
5
|
+
import { TestContractParams, setCurrentNodeProvider, Project } from '@alephium/web3'
|
|
6
|
+
import { testNodeWallet } from '@alephium/web3/test'
|
|
7
7
|
|
|
8
8
|
async function greet() {
|
|
9
|
-
|
|
9
|
+
setCurrentNodeProvider('http://127.0.0.1:22973')
|
|
10
|
+
await Project.build()
|
|
10
11
|
|
|
11
|
-
const greeter =
|
|
12
|
+
const greeter = Project.contract('greeter/greeter.ral')
|
|
12
13
|
|
|
13
14
|
const testParams: TestContractParams = {
|
|
14
15
|
initialFields: { btcPrice: 1 }
|
|
15
16
|
}
|
|
16
|
-
const testResult = await greeter.testPublicMethod(
|
|
17
|
+
const testResult = await greeter.testPublicMethod('greet', testParams)
|
|
17
18
|
console.log(testResult)
|
|
18
19
|
|
|
19
|
-
const signer = await
|
|
20
|
+
const signer = await testNodeWallet()
|
|
20
21
|
|
|
21
22
|
const deployTx = await greeter.transactionForDeployment(signer, { initialFields: testParams.initialFields })
|
|
22
23
|
const greeterContractId = deployTx.contractId
|
|
@@ -26,7 +27,7 @@ async function greet() {
|
|
|
26
27
|
const submitResult = await signer.submitTransaction(deployTx.unsignedTx, deployTx.txId)
|
|
27
28
|
console.log(submitResult)
|
|
28
29
|
|
|
29
|
-
const main =
|
|
30
|
+
const main = Project.script('greeter_main.ral')
|
|
30
31
|
|
|
31
32
|
const mainScriptTx = await main.transactionForDeployment(signer, {
|
|
32
33
|
initialFields: { greeterContractId: greeterContractId }
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "my-dapp",
|
|
3
3
|
"version": "0.1.0",
|
|
4
4
|
"config": {
|
|
5
|
-
"alephium_version": "1.5.0-
|
|
5
|
+
"alephium_version": "1.5.0-rc7"
|
|
6
6
|
},
|
|
7
7
|
"dependencies": {
|
|
8
8
|
"@testing-library/jest-dom": "^5.16.4",
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
"@types/node": "^16.11.26",
|
|
13
13
|
"@types/react": "^18.0.3",
|
|
14
14
|
"@types/react-dom": "^18.0.0",
|
|
15
|
-
"@alephium/web3": "0.2.0-rc.
|
|
15
|
+
"@alephium/web3": "0.2.0-rc.7",
|
|
16
16
|
"react": "^18.0.0",
|
|
17
17
|
"react-dom": "^18.0.0",
|
|
18
18
|
"react-scripts": "5.0.1",
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import React, { useEffect, useState } from 'react'
|
|
2
2
|
import './App.css'
|
|
3
3
|
|
|
4
|
-
import {
|
|
4
|
+
import { ExplorerProvider, Contract, Script } from '@alephium/web3'
|
|
5
5
|
import contractJson from './artifacts/greeter.ral.json'
|
|
6
6
|
import scriptJson from './artifacts/greeter_main.ral.json'
|
|
7
7
|
|
|
8
8
|
function Dashboard() {
|
|
9
|
-
const api = new
|
|
9
|
+
const api = new ExplorerProvider('https://mainnet-backend.alephium.org')
|
|
10
10
|
const contract = Contract.fromJson(contractJson).toString()
|
|
11
11
|
const script = Script.fromJson(scriptJson).toString()
|
|
12
12
|
const [blocks, setBlocks] = useState('')
|