@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.
Files changed (83) hide show
  1. package/.eslintignore +2 -2
  2. package/README.md +2 -135
  3. package/contracts/greeter/greeter.ral +1 -1
  4. package/dist/alephium-web3.min.js +1 -1
  5. package/dist/alephium-web3.min.js.LICENSE.txt +0 -17
  6. package/dist/alephium-web3.min.js.map +1 -1
  7. package/dist/scripts/create-project.js +1 -1
  8. package/dist/src/api/api-alephium.d.ts +19 -6
  9. package/dist/src/api/api-explorer.d.ts +16 -16
  10. package/dist/src/api/index.js +5 -1
  11. package/dist/src/contract/contract.d.ts +30 -8
  12. package/dist/src/contract/contract.js +105 -58
  13. package/dist/src/contract/index.js +5 -1
  14. package/dist/src/global.d.ts +3 -0
  15. package/{src/utils/djb2.test.ts → dist/src/global.js} +20 -17
  16. package/dist/src/index.d.ts +2 -0
  17. package/dist/src/index.js +20 -1
  18. package/dist/src/signer/index.d.ts +0 -1
  19. package/dist/src/signer/index.js +5 -2
  20. package/dist/src/signer/signer.d.ts +1 -1
  21. package/dist/src/signer/signer.js +8 -3
  22. package/dist/src/transaction/index.d.ts +0 -1
  23. package/dist/src/transaction/index.js +5 -2
  24. package/dist/src/utils/index.d.ts +0 -1
  25. package/dist/src/utils/index.js +5 -2
  26. package/dist/src/utils/subscription.d.ts +0 -1
  27. package/dist/src/utils/subscription.js +2 -1
  28. package/dist/src/utils/utils.d.ts +3 -2
  29. package/dist/src/utils/utils.js +16 -15
  30. package/jest-config.json +11 -0
  31. package/package.json +6 -32
  32. package/scripts/create-project.ts +1 -1
  33. package/src/api/api-alephium.ts +14 -0
  34. package/src/contract/contract.ts +161 -65
  35. package/src/{test/index.ts → global.ts} +14 -10
  36. package/src/index.ts +3 -0
  37. package/src/signer/index.ts +0 -1
  38. package/src/signer/signer.ts +3 -2
  39. package/src/transaction/index.ts +0 -1
  40. package/src/utils/index.ts +0 -1
  41. package/src/utils/subscription.ts +2 -2
  42. package/src/utils/utils.ts +7 -7
  43. package/templates/base/package.json +2 -2
  44. package/templates/base/src/greeter.ts +8 -7
  45. package/templates/react/package.json +2 -2
  46. package/templates/react/src/App.tsx +2 -2
  47. package/.eslintrc.json +0 -21
  48. package/LICENSE +0 -165
  49. package/contracts/add/add.ral +0 -15
  50. package/contracts/main.ral +0 -4
  51. package/contracts/sub/sub.ral +0 -10
  52. package/contracts/test/metadata.ral +0 -18
  53. package/contracts/test/warnings.ral +0 -8
  54. package/dist/src/signer/node-wallet.d.ts +0 -13
  55. package/dist/src/signer/node-wallet.js +0 -60
  56. package/dist/src/test/index.d.ts +0 -7
  57. package/dist/src/test/index.js +0 -41
  58. package/dist/src/test/privatekey-wallet.d.ts +0 -12
  59. package/dist/src/test/privatekey-wallet.js +0 -68
  60. package/dist/src/transaction/sign-verify.d.ts +0 -2
  61. package/dist/src/transaction/sign-verify.js +0 -58
  62. package/dist/src/utils/password-crypto.d.ts +0 -2
  63. package/dist/src/utils/password-crypto.js +0 -69
  64. package/gitignore +0 -9
  65. package/src/contract/ralph.test.ts +0 -178
  66. package/src/fixtures/address.json +0 -36
  67. package/src/fixtures/balance.json +0 -9
  68. package/src/fixtures/self-clique.json +0 -19
  69. package/src/fixtures/transaction.json +0 -13
  70. package/src/fixtures/transactions.json +0 -179
  71. package/src/signer/fixtures/genesis.json +0 -26
  72. package/src/signer/fixtures/wallets.json +0 -26
  73. package/src/signer/node-wallet.ts +0 -74
  74. package/src/test/privatekey-wallet.ts +0 -58
  75. package/src/transaction/sign-verify.test.ts +0 -50
  76. package/src/transaction/sign-verify.ts +0 -39
  77. package/src/utils/address.test.ts +0 -47
  78. package/src/utils/password-crypto.test.ts +0 -27
  79. package/src/utils/password-crypto.ts +0 -77
  80. package/src/utils/utils.test.ts +0 -161
  81. package/test/contract.test.ts +0 -213
  82. package/test/events.test.ts +0 -143
  83. package/test/transaction.test.ts +0 -74
@@ -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 * as cryptojs from 'crypto-js'
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 = cryptojs.SHA256(sourceCode).toString()
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
- constructor(infos: Map<string, { sourceCodeHash: string; warnings: string[] }>) {
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 content = JSON.stringify(Object.fromEntries(this.infos), null, 2)
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
- sourceHasChanged(files: SourceFile[]): boolean {
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 files = new Map(
122
- Object.entries<{ sourceCodeHash: string; warnings: string[] }>(JSON.parse(content.toString()))
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
- private static checkCompilerWarnings(
178
- warnings: string[],
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 + remains.join('\n' + prefixPerWarning)
186
- const output = 'Compilation warnings:\n' + warningString + '\n'
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, errorOnWarnings = true, ignoreUnusedConstantsWarnings = true): Contract {
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, errorOnWarnings = true, ignoreUnusedConstantsWarnings = true): Script {
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 project = new Project(provider, contractsRootPath, artifactsRootPath, files, contracts, scripts)
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
- return new Project(provider, contractsRootPath, artifactsRootPath, files, contracts, scripts)
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 new SourceFile(type, sourceStr, contractPath)
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
- provider: NodeProvider,
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.sourceHasChanged(sourceFiles)) {
379
- Project.currentProject = await Project.compile(provider, sourceFiles, contractsRootPath, artifactsRootPath)
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 = crypto.randomBytes(33)
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 '../api'
20
- import { NodeWallet } from '../signer'
19
+ import { NodeProvider } from './api'
21
20
 
22
- export const testWalletName = 'alephium-web3-test-only-wallet'
23
- export const testAddress = '1DrDyTr9RpRsQnDnXo2YRiPzPW4ooHX5LLoqXrqfMrpQH'
24
- export const testPassword = 'alph'
21
+ let _currentNodeProvider: NodeProvider | undefined = undefined
25
22
 
26
- export async function testWallet(provider: NodeProvider): Promise<NodeWallet> {
27
- const wallet = new NodeWallet(provider, testWalletName)
28
- await wallet.unlock(testPassword)
29
- return wallet
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 * from './privatekey-wallet'
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
@@ -23,3 +23,6 @@ export * from './utils'
23
23
  export * from './transaction'
24
24
 
25
25
  export * from './constants'
26
+ export * from './global'
27
+
28
+ export * as utils from './utils'
@@ -17,4 +17,3 @@ along with the library. If not, see <http://www.gnu.org/licenses/>.
17
17
  */
18
18
 
19
19
  export * from './signer'
20
- export * from './node-wallet'
@@ -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(provider: NodeProvider, alwaysSubmitTx: boolean) {
171
- this.provider = provider
171
+ constructor(alwaysSubmitTx: boolean) {
172
+ this.provider = getCurrentNodeProvider()
172
173
  this.alwaysSubmitTx = alwaysSubmitTx
173
174
  }
174
175
 
@@ -16,5 +16,4 @@ 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
- export * from './sign-verify'
20
19
  export * from './status'
@@ -19,6 +19,5 @@ along with the library. If not, see <http://www.gnu.org/licenses/>.
19
19
  export * from './address'
20
20
  export * from './bs58'
21
21
  export * from './djb2'
22
- export * from './password-crypto'
23
22
  export * from './utils'
24
23
  export * from './subscription'
@@ -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 = options.provider
43
+ this.provider = getCurrentNodeProvider()
44
44
  this.pollingInterval = options.pollingInterval
45
45
  this.messageCallback = options.messageCallback
46
46
  this.errorCallback = options.errorCallback
@@ -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 const signatureDecode = (ec: EC, signature: string): SignatureInput => {
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
- const xorByte = (intValue: number) => {
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 const groupOfAddress = (address: string): number => {
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
- const groupOfAddressBytes = (bytes: Uint8Array): number => {
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
- const groupOfP2pkhAddress = (address: Uint8Array): number => {
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
- const groupOfP2mpkhAddress = (address: Uint8Array): number => {
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
- const groupOfP2shAddress = (address: Uint8Array): number => {
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-rc5"
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.5"
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 { NodeProvider, Contract, Script, TestContractParams } from '@alephium/web3'
6
- import { testWallet } from '@alephium/web3/test'
5
+ import { TestContractParams, setCurrentNodeProvider, Project } from '@alephium/web3'
6
+ import { testNodeWallet } from '@alephium/web3/test'
7
7
 
8
8
  async function greet() {
9
- const provider = new NodeProvider('http://127.0.0.1:22973')
9
+ setCurrentNodeProvider('http://127.0.0.1:22973')
10
+ await Project.build()
10
11
 
11
- const greeter = await Contract.fromSource(provider, 'greeter.ral')
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(provider, 'greet', testParams)
17
+ const testResult = await greeter.testPublicMethod('greet', testParams)
17
18
  console.log(testResult)
18
19
 
19
- const signer = await testWallet(provider)
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 = await Script.fromSource(provider, 'greeter_main.ral')
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-rc5"
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.5",
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 { explorer, Contract, Script } from '@alephium/web3'
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 explorer.Api<null>({ baseUrl: 'https://mainnet-backend.alephium.org' })
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('')