@alephium/web3 0.1.0 → 0.2.0-test.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. package/contracts/{add.ral → add/add.ral} +1 -1
  2. package/contracts/{greeter.ral → greeter/greeter.ral} +0 -0
  3. package/contracts/{greeter_interface.ral → greeter/greeter_interface.ral} +0 -0
  4. package/contracts/greeter_main.ral +1 -1
  5. package/contracts/main.ral +1 -1
  6. package/contracts/{sub.ral → sub/sub.ral} +0 -0
  7. package/dist/alephium-web3.min.js +1 -1
  8. package/dist/alephium-web3.min.js.map +1 -1
  9. package/dist/src/api/api-alephium.d.ts +2 -0
  10. package/dist/src/contract/contract.d.ts +18 -10
  11. package/dist/src/contract/contract.js +95 -56
  12. package/dist/src/contract/events.d.ts +7 -25
  13. package/dist/src/contract/events.js +18 -31
  14. package/dist/src/index.d.ts +1 -0
  15. package/dist/src/index.js +1 -0
  16. package/dist/src/transaction/index.d.ts +2 -0
  17. package/dist/src/transaction/index.js +31 -0
  18. package/dist/src/{utils/transaction.d.ts → transaction/sign-verify.d.ts} +0 -0
  19. package/dist/src/{utils/transaction.js → transaction/sign-verify.js} +1 -1
  20. package/dist/src/transaction/status.d.ts +10 -0
  21. package/dist/src/transaction/status.js +48 -0
  22. package/dist/src/utils/index.d.ts +1 -1
  23. package/dist/src/utils/index.js +1 -1
  24. package/dist/src/utils/subscription.d.ts +24 -0
  25. package/dist/src/utils/subscription.js +52 -0
  26. package/dist/src/utils/utils.d.ts +2 -0
  27. package/dist/src/utils/utils.js +9 -1
  28. package/package.json +1 -1
  29. package/src/api/api-alephium.ts +2 -0
  30. package/src/contract/contract.ts +112 -66
  31. package/src/contract/events.ts +21 -48
  32. package/src/index.ts +1 -0
  33. package/src/transaction/index.ts +20 -0
  34. package/src/{utils/transaction.test.ts → transaction/sign-verify.test.ts} +1 -1
  35. package/src/{utils/transaction.ts → transaction/sign-verify.ts} +1 -1
  36. package/src/transaction/status.ts +58 -0
  37. package/src/utils/index.ts +1 -1
  38. package/src/utils/subscription.ts +72 -0
  39. package/src/utils/utils.test.ts +2 -1
  40. package/src/utils/utils.ts +8 -0
  41. package/test/contract.test.ts +24 -7
  42. package/test/events.test.ts +18 -19
  43. package/test/transaction.test.ts +72 -0
@@ -0,0 +1,52 @@
1
+ "use strict";
2
+ /*
3
+ Copyright 2018 - 2022 The Alephium Authors
4
+ This file is part of the alephium project.
5
+
6
+ The library is free software: you can redistribute it and/or modify
7
+ it under the terms of the GNU Lesser General Public License as published by
8
+ the Free Software Foundation, either version 3 of the License, or
9
+ (at your option) any later version.
10
+
11
+ The library is distributed in the hope that it will be useful,
12
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ GNU Lesser General Public License for more details.
15
+
16
+ You should have received a copy of the GNU Lesser General Public License
17
+ along with the library. If not, see <http://www.gnu.org/licenses/>.
18
+ */
19
+ var __importDefault = (this && this.__importDefault) || function (mod) {
20
+ return (mod && mod.__esModule) ? mod : { "default": mod };
21
+ };
22
+ Object.defineProperty(exports, "__esModule", { value: true });
23
+ exports.Subscription = void 0;
24
+ const eventemitter3_1 = __importDefault(require("eventemitter3"));
25
+ class Subscription {
26
+ constructor(options) {
27
+ this.provider = options.provider;
28
+ this.pollingInterval = options.pollingInterval;
29
+ this.messageCallback = options.messageCallback;
30
+ this.errorCallback = options.errorCallback;
31
+ this.task = undefined;
32
+ this.cancelled = false;
33
+ this.eventEmitter = new eventemitter3_1.default();
34
+ }
35
+ startPolling() {
36
+ this.eventEmitter.on('tick', async () => {
37
+ await this.polling();
38
+ if (!this.cancelled) {
39
+ this.task = setTimeout(() => this.eventEmitter.emit('tick'), this.pollingInterval);
40
+ }
41
+ });
42
+ this.eventEmitter.emit('tick');
43
+ }
44
+ unsubscribe() {
45
+ this.eventEmitter.removeAllListeners();
46
+ this.cancelled = true;
47
+ if (typeof this.task !== 'undefined') {
48
+ clearTimeout(this.task);
49
+ }
50
+ }
51
+ }
52
+ exports.Subscription = Subscription;
@@ -20,6 +20,8 @@ export declare function addressFromContractId(contractId: string): string;
20
20
  export declare function contractIdFromTx(txId: string, outputIndex: number): string;
21
21
  export declare function subContractId(parentContractId: string, pathInHex: string): string;
22
22
  export declare function stringToHex(str: string): string;
23
+ export declare function hexToString(str: any): string;
24
+ export declare function timeout(ms: number): Promise<unknown>;
23
25
  declare type _Eq<X, Y> = (<T>() => T extends X ? 1 : 2) extends <T>() => T extends Y ? 1 : 2 ? true : false;
24
26
  export declare type Eq<X, Y> = _Eq<{
25
27
  [P in keyof X]: X[P];
@@ -20,7 +20,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
20
20
  return (mod && mod.__esModule) ? mod : { "default": mod };
21
21
  };
22
22
  Object.defineProperty(exports, "__esModule", { value: true });
23
- exports.assertType = exports.stringToHex = exports.subContractId = exports.contractIdFromTx = exports.addressFromContractId = exports.addressFromPublicKey = exports.publicKeyFromPrivateKey = exports.binToHex = exports.hexToBinUnsafe = exports.tokenIdFromAddress = exports.contractIdFromAddress = exports.groupOfAddress = exports.isHexString = exports.signatureDecode = exports.signatureEncode = exports.convertHttpResponse = void 0;
23
+ exports.assertType = exports.timeout = exports.hexToString = exports.stringToHex = exports.subContractId = exports.contractIdFromTx = exports.addressFromContractId = exports.addressFromPublicKey = exports.publicKeyFromPrivateKey = exports.binToHex = exports.hexToBinUnsafe = exports.tokenIdFromAddress = exports.contractIdFromAddress = exports.groupOfAddress = exports.isHexString = exports.signatureDecode = exports.signatureEncode = exports.convertHttpResponse = void 0;
24
24
  const elliptic_1 = require("elliptic");
25
25
  const bn_js_1 = __importDefault(require("bn.js"));
26
26
  const blakejs_1 = __importDefault(require("blakejs"));
@@ -194,6 +194,14 @@ function stringToHex(str) {
194
194
  return hex;
195
195
  }
196
196
  exports.stringToHex = stringToHex;
197
+ function hexToString(str) {
198
+ return buffer_1.Buffer.from(str.toString(), 'hex').toString();
199
+ }
200
+ exports.hexToString = hexToString;
201
+ function timeout(ms) {
202
+ return new Promise((resolve) => setTimeout(resolve, ms));
203
+ }
204
+ exports.timeout = timeout;
197
205
  // eslint-disable-next-line @typescript-eslint/no-empty-function, @typescript-eslint/no-unused-vars
198
206
  function assertType() { }
199
207
  exports.assertType = assertType;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@alephium/web3",
3
- "version": "0.1.0",
3
+ "version": "0.2.0-test.0",
4
4
  "description": "A JS/TS library to interact with the Alephium platform",
5
5
  "license": "GPL",
6
6
  "main": "dist/src/index.js",
@@ -96,6 +96,8 @@ export interface Balance {
96
96
 
97
97
  /** @format x.x ALPH */
98
98
  lockedBalanceHint: string
99
+ tokenBalances?: Token[]
100
+ lockedTokenBalances?: Token[]
99
101
 
100
102
  /** @format int32 */
101
103
  utxoNum: number
@@ -27,11 +27,30 @@ import { SignDeployContractTxParams, SignExecuteScriptTxParams, SignerWithNodePr
27
27
  import * as ralph from './ralph'
28
28
  import { bs58, binToHex, contractIdFromAddress, assertType, Eq } from '../utils'
29
29
 
30
+ class SourceFile {
31
+ readonly dirs: string[]
32
+ readonly dirPath: string
33
+ readonly contractPath: string
34
+ readonly artifactPath: string
35
+
36
+ constructor(dirs: string[], fileName: string) {
37
+ this.dirs = dirs
38
+ this.dirPath = dirs.length === 0 ? '' : dirs.join('/') + '/'
39
+ if (fileName.endsWith('.json')) {
40
+ this.contractPath = './contracts/' + this.dirPath + fileName.slice(0, -5)
41
+ this.artifactPath = './artifacts/' + this.dirPath + fileName
42
+ } else {
43
+ this.contractPath = './contracts/' + this.dirPath + fileName
44
+ this.artifactPath = './artifacts/' + this.dirPath + fileName + '.json'
45
+ }
46
+ }
47
+ }
48
+
30
49
  export abstract class Common {
31
50
  readonly sourceCodeSha256: string
32
51
  readonly functions: node.FunctionSig[]
33
52
 
34
- static readonly importRegex = new RegExp('^import "[a-z][a-z_0-9]*.ral"', 'mg')
53
+ static readonly importRegex = new RegExp('^import "([^"/]+/(([^"]+)/)?)?[a-z][a-z_0-9]*.ral"', 'mg')
35
54
  static readonly contractRegex = new RegExp('^TxContract [A-Z][a-zA-Z0-9]*', 'mg')
36
55
  static readonly interfaceRegex = new RegExp('^Interface [A-Z][a-zA-Z0-9]* \\{', 'mg')
37
56
  static readonly scriptRegex = new RegExp('^TxScript [A-Z][a-zA-Z0-9]*', 'mg')
@@ -56,38 +75,53 @@ export abstract class Common {
56
75
  this.functions = functions
57
76
  }
58
77
 
59
- protected static _contractPath(fileName: string): string {
60
- if (fileName.endsWith('.json')) {
61
- return `./contracts/${fileName.slice(0, -5)}`
62
- } else {
63
- return `./contracts/${fileName}`
64
- }
78
+ protected static _artifactsFolder(): string {
79
+ return './artifacts/'
65
80
  }
66
81
 
67
- protected static _artifactPath(fileName: string): string {
68
- if (fileName.endsWith('.json')) {
69
- return `./artifacts/${fileName}`
70
- } else {
71
- return `./artifacts/${fileName}.json`
82
+ static getSourceFile(path: string, _dirs: string[]): SourceFile {
83
+ const parts = path.split('/')
84
+ const dirs = Array.from(_dirs)
85
+ if (parts.length === 1) {
86
+ return new SourceFile(dirs, path)
72
87
  }
88
+ parts.slice(0, parts.length - 1).forEach((part) => {
89
+ switch (part) {
90
+ case '.': {
91
+ break
92
+ }
93
+ case '..': {
94
+ if (dirs.length === 0) {
95
+ throw new Error('Invalid file path: ' + path)
96
+ }
97
+ dirs.pop()
98
+ break
99
+ }
100
+ default: {
101
+ dirs.push(part)
102
+ }
103
+ }
104
+ })
105
+ return new SourceFile(dirs, parts[parts.length - 1])
73
106
  }
74
107
 
75
- protected static _artifactsFolder(): string {
76
- return './artifacts/'
77
- }
78
-
79
- protected static async _handleImports(contractStr: string, importsCache: string[]): Promise<string> {
108
+ protected static async _handleImports(
109
+ pathes: string[],
110
+ contractStr: string,
111
+ importsCache: string[]
112
+ ): Promise<string> {
80
113
  const localImportsCache: string[] = []
81
114
  let result = contractStr.replace(Common.importRegex, (match) => {
82
115
  localImportsCache.push(match)
83
116
  return ''
84
117
  })
85
118
  for (const myImport of localImportsCache) {
86
- const fileName = myImport.slice(8, -1)
87
- if (!importsCache.includes(fileName)) {
88
- importsCache.push(fileName)
89
- const importContractStr = await Common._loadContractStr(fileName, importsCache, (code) =>
90
- Contract.checkCodeType(fileName, code)
119
+ const relativePath = myImport.slice(8, -1)
120
+ const importSourceFile = this.getSourceFile(relativePath, pathes)
121
+ if (!importsCache.includes(importSourceFile.contractPath)) {
122
+ importsCache.push(importSourceFile.contractPath)
123
+ const importContractStr = await Common._loadContractStr(importSourceFile, importsCache, (code) =>
124
+ Contract.checkCodeType(importSourceFile.contractPath, code)
91
125
  )
92
126
  result = result.concat('\n', importContractStr)
93
127
  }
@@ -96,16 +130,16 @@ export abstract class Common {
96
130
  }
97
131
 
98
132
  protected static async _loadContractStr(
99
- fileName: string,
133
+ sourceFile: SourceFile,
100
134
  importsCache: string[],
101
- validate: (fileName: string) => void
135
+ validate: (code: string) => void
102
136
  ): Promise<string> {
103
- const contractPath = this._contractPath(fileName)
137
+ const contractPath = sourceFile.contractPath
104
138
  const contractBuffer = await fsPromises.readFile(contractPath)
105
139
  const contractStr = contractBuffer.toString()
106
140
 
107
141
  validate(contractStr)
108
- return Common._handleImports(contractStr, importsCache)
142
+ return Common._handleImports(sourceFile.dirs, contractStr, importsCache)
109
143
  }
110
144
 
111
145
  static checkFileNameExtension(fileName: string): void {
@@ -116,25 +150,28 @@ export abstract class Common {
116
150
 
117
151
  protected static async _from<T extends { sourceCodeSha256: string }>(
118
152
  provider: NodeProvider,
119
- fileName: string,
120
- loadContractStr: (fileName: string, importsCache: string[]) => Promise<string>,
121
- compile: (provider: NodeProvider, fileName: string, contractStr: string, contractHash: string) => Promise<T>
153
+ sourceFile: SourceFile,
154
+ loadContractStr: (sourceFile: SourceFile, importsCache: string[]) => Promise<string>,
155
+ compile: (provider: NodeProvider, sourceFile: SourceFile, contractStr: string, contractHash: string) => Promise<T>
122
156
  ): Promise<T> {
123
- Common.checkFileNameExtension(fileName)
157
+ Common.checkFileNameExtension(sourceFile.contractPath)
124
158
 
125
- const contractStr = await loadContractStr(fileName, [])
159
+ const contractStr = await loadContractStr(sourceFile, [])
126
160
  const contractHash = cryptojs.SHA256(contractStr).toString()
127
161
  const existingContract = this._getArtifactFromCache(contractHash)
128
162
  if (typeof existingContract !== 'undefined') {
129
163
  return existingContract as unknown as T
130
164
  } else {
131
- return compile(provider, fileName, contractStr, contractHash)
165
+ return compile(provider, sourceFile, contractStr, contractHash)
132
166
  }
133
167
  }
134
168
 
135
- protected _saveToFile(fileName: string): Promise<void> {
136
- const artifactPath = Common._artifactPath(fileName)
137
- return fsPromises.writeFile(artifactPath, this.toString())
169
+ protected _saveToFile(sourceFile: SourceFile): Promise<void> {
170
+ const folder = Common._artifactsFolder() + sourceFile.dirPath
171
+ if (!fs.existsSync(folder)) {
172
+ fs.mkdirSync(folder, { recursive: true })
173
+ }
174
+ return fsPromises.writeFile(sourceFile.artifactPath, this.toString())
138
175
  }
139
176
 
140
177
  abstract buildByteCodeToDeploy(initialFields?: Fields): string
@@ -163,32 +200,38 @@ export class Contract extends Common {
163
200
 
164
201
  static checkCodeType(fileName: string, contractStr: string): void {
165
202
  const interfaceMatches = contractStr.match(Contract.interfaceRegex)
166
- if (interfaceMatches) {
167
- return
168
- }
169
-
170
203
  const contractMatches = contractStr.match(Contract.contractRegex)
171
- if (contractMatches === null) {
204
+ if (interfaceMatches === null && contractMatches === null) {
172
205
  throw new Error(`No contract found in: ${fileName}`)
173
- } else if (contractMatches.length > 1) {
174
- throw new Error(`Multiple contracts in: ${fileName}`)
175
- } else {
176
- return
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
+ }
177
219
  }
178
220
  }
179
221
 
180
- private static async loadContractStr(fileName: string, importsCache: string[]): Promise<string> {
181
- return Common._loadContractStr(fileName, importsCache, (code) => Contract.checkCodeType(fileName, code))
222
+ private static async loadContractStr(sourceFile: SourceFile): Promise<string> {
223
+ return Common._loadContractStr(sourceFile, [], (code) => Contract.checkCodeType(sourceFile.contractPath, code))
182
224
  }
183
225
 
184
- static async fromSource(provider: NodeProvider, fileName: string): Promise<Contract> {
226
+ static async fromSource(provider: NodeProvider, path: string): Promise<Contract> {
185
227
  if (!fs.existsSync(Common._artifactsFolder())) {
186
228
  fs.mkdirSync(Common._artifactsFolder(), { recursive: true })
187
229
  }
230
+ const sourceFile = this.getSourceFile(path, [])
188
231
  const contract = await Common._from(
189
232
  provider,
190
- fileName,
191
- (fileName, importCaches) => Contract.loadContractStr(fileName, importCaches),
233
+ sourceFile,
234
+ (sourceFile) => Contract.loadContractStr(sourceFile),
192
235
  Contract.compile
193
236
  )
194
237
  this._putArtifactToCache(contract)
@@ -197,7 +240,7 @@ export class Contract extends Common {
197
240
 
198
241
  private static async compile(
199
242
  provider: NodeProvider,
200
- fileName: string,
243
+ sourceFile: SourceFile,
201
244
  contractStr: string,
202
245
  contractHash: string
203
246
  ): Promise<Contract> {
@@ -210,7 +253,7 @@ export class Contract extends Common {
210
253
  compiled.events,
211
254
  compiled.functions
212
255
  )
213
- await artifact._saveToFile(fileName)
256
+ await artifact._saveToFile(sourceFile)
214
257
  return artifact
215
258
  }
216
259
 
@@ -239,13 +282,19 @@ export class Contract extends Common {
239
282
  }
240
283
 
241
284
  // support both 'code.ral' and 'code.ral.json'
242
- static async fromArtifactFile(fileName: string): Promise<Contract> {
243
- const artifactPath = Contract._artifactPath(fileName)
285
+ static async fromArtifactFile(path: string): Promise<Contract> {
286
+ const sourceFile = this.getSourceFile(path, [])
287
+ const artifactPath = sourceFile.artifactPath
244
288
  const content = await fsPromises.readFile(artifactPath)
245
289
  const artifact = JSON.parse(content.toString())
246
290
  return Contract.fromJson(artifact)
247
291
  }
248
292
 
293
+ async fetchState(provider: NodeProvider, address: string, group: number): Promise<ContractState> {
294
+ const state = await provider.contracts.getContractsAddressState(address, { group: group })
295
+ return this.fromApiContractState(state)
296
+ }
297
+
249
298
  override toString(): string {
250
299
  return JSON.stringify(
251
300
  {
@@ -518,28 +567,24 @@ export class Script extends Common {
518
567
  }
519
568
  }
520
569
 
521
- private static async loadContractStr(fileName: string, importsCache: string[]): Promise<string> {
522
- return Common._loadContractStr(fileName, importsCache, (code) => Script.checkCodeType(fileName, code))
570
+ private static async loadContractStr(sourceFile: SourceFile): Promise<string> {
571
+ return Common._loadContractStr(sourceFile, [], (code) => Script.checkCodeType(sourceFile.contractPath, code))
523
572
  }
524
573
 
525
- static async fromSource(provider: NodeProvider, fileName: string): Promise<Script> {
526
- return Common._from(
527
- provider,
528
- fileName,
529
- (fileName, importsCache) => Script.loadContractStr(fileName, importsCache),
530
- Script.compile
531
- )
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)
532
577
  }
533
578
 
534
579
  private static async compile(
535
580
  provider: NodeProvider,
536
- fileName: string,
581
+ sourceFile: SourceFile,
537
582
  scriptStr: string,
538
583
  contractHash: string
539
584
  ): Promise<Script> {
540
585
  const compiled = await provider.contracts.postContractsCompileScript({ code: scriptStr })
541
586
  const artifact = new Script(contractHash, compiled.bytecodeTemplate, compiled.fields, compiled.functions)
542
- await artifact._saveToFile(fileName)
587
+ await artifact._saveToFile(sourceFile)
543
588
  return artifact
544
589
  }
545
590
 
@@ -556,8 +601,9 @@ export class Script extends Common {
556
601
  return new Script(artifact.sourceCodeSha256, artifact.bytecodeTemplate, artifact.fieldsSig, artifact.functions)
557
602
  }
558
603
 
559
- static async fromArtifactFile(fileName: string): Promise<Script> {
560
- const artifactPath = Common._artifactPath(fileName)
604
+ static async fromArtifactFile(path: string): Promise<Script> {
605
+ const sourceFile = this.getSourceFile(path, [])
606
+ const artifactPath = sourceFile.artifactPath
561
607
  const content = await fsPromises.readFile(artifactPath)
562
608
  const artifact = JSON.parse(content.toString())
563
609
  return this.fromJson(artifact)
@@ -16,64 +16,33 @@ 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 EventEmitter from 'eventemitter3'
20
- import { node } from '../api'
21
- import { NodeProvider } from '../api'
19
+ import { ContractEvent } from '../api/api-alephium'
20
+ import { Subscription, SubscribeOptions } from '../utils'
22
21
 
23
- type EventCallback = (event: node.ContractEvent) => Promise<void>
24
- type ErrorCallback = (error: any, subscription: Subscription) => Promise<void>
25
-
26
- export interface SubscribeOptions {
27
- provider: NodeProvider
28
- contractAddress: string
29
- fromCount?: number
30
- pollingInterval: number
31
- eventCallback: EventCallback
32
- errorCallback: ErrorCallback
33
- }
34
-
35
- export class Subscription {
36
- provider: NodeProvider
22
+ export class EventSubscription extends Subscription<ContractEvent> {
37
23
  readonly contractAddress: string
38
- pollingInterval: number
39
-
40
24
  private fromCount: number
41
- private eventCallback: EventCallback
42
- private errorCallback: ErrorCallback
43
- private task: ReturnType<typeof setTimeout> | undefined
44
- private cancelled: boolean
45
- private eventEmitter: EventEmitter
46
25
 
47
- constructor(options: SubscribeOptions) {
48
- this.provider = options.provider
49
- this.contractAddress = options.contractAddress
50
- this.fromCount = typeof options.fromCount === 'undefined' ? 0 : options.fromCount
51
- this.pollingInterval = options.pollingInterval
52
- this.eventCallback = options.eventCallback
53
- this.errorCallback = options.errorCallback
54
- this.task = undefined
55
- this.cancelled = false
26
+ constructor(options: SubscribeOptions<ContractEvent>, contractAddress: string, fromCount?: number) {
27
+ super(options)
28
+ this.contractAddress = contractAddress
29
+ this.fromCount = typeof fromCount === 'undefined' ? 0 : fromCount
56
30
 
57
- this.eventEmitter = new EventEmitter()
31
+ this.startPolling()
32
+ }
33
+
34
+ override startPolling() {
58
35
  this.eventEmitter.on('tick', async () => {
59
- await this.fetchEvents()
36
+ await this.polling()
60
37
  })
61
38
  this.eventEmitter.emit('tick')
62
39
  }
63
40
 
64
- unsubscribe(): void {
65
- this.eventEmitter.removeAllListeners()
66
- this.cancelled = true
67
- if (typeof this.task !== 'undefined') {
68
- clearTimeout(this.task)
69
- }
70
- }
71
-
72
41
  currentEventCount(): number {
73
42
  return this.fromCount
74
43
  }
75
44
 
76
- private async fetchEvents() {
45
+ override async polling() {
77
46
  try {
78
47
  const events = await this.provider.events.getEventsContractContractaddress(this.contractAddress, {
79
48
  start: this.fromCount
@@ -87,16 +56,20 @@ export class Subscription {
87
56
  return
88
57
  }
89
58
 
90
- const promises = events.events.map((event) => this.eventCallback(event))
59
+ const promises = events.events.map((event) => this.messageCallback(event))
91
60
  await Promise.all(promises)
92
61
  this.fromCount = events.nextStart
93
- await this.fetchEvents()
62
+ await this.polling()
94
63
  } catch (err) {
95
64
  await this.errorCallback(err, this)
96
65
  }
97
66
  }
98
67
  }
99
68
 
100
- export function subscribe(options: SubscribeOptions): Subscription {
101
- return new Subscription(options)
69
+ export function subscribeToEvents(
70
+ options: SubscribeOptions<ContractEvent>,
71
+ contractAddress: string,
72
+ fromCount?: number
73
+ ): EventSubscription {
74
+ return new EventSubscription(options, contractAddress, fromCount)
102
75
  }
package/src/index.ts CHANGED
@@ -20,5 +20,6 @@ export * from './api'
20
20
  export * from './contract'
21
21
  export * from './signer'
22
22
  export * from './utils'
23
+ export * from './transaction'
23
24
 
24
25
  export * from './constants'
@@ -0,0 +1,20 @@
1
+ /*
2
+ Copyright 2018 - 2022 The Alephium Authors
3
+ This file is part of the alephium project.
4
+
5
+ The library is free software: you can redistribute it and/or modify
6
+ it under the terms of the GNU Lesser General Public License as published by
7
+ the Free Software Foundation, either version 3 of the License, or
8
+ (at your option) any later version.
9
+
10
+ The library is distributed in the hope that it will be useful,
11
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ GNU Lesser General Public License for more details.
14
+
15
+ You should have received a copy of the GNU Lesser General Public License
16
+ along with the library. If not, see <http://www.gnu.org/licenses/>.
17
+ */
18
+
19
+ export * from './sign-verify'
20
+ export * from './status'
@@ -19,7 +19,7 @@ along with the library. If not, see <http://www.gnu.org/licenses/>.
19
19
  import EC from 'elliptic'
20
20
  import assert from 'assert'
21
21
 
22
- import { transactionSign, transactionVerifySignature } from './transaction'
22
+ import { transactionSign, transactionVerifySignature } from './sign-verify'
23
23
 
24
24
  describe('transaction', function () {
25
25
  it('should verify signature', () => {
@@ -18,7 +18,7 @@ along with the library. If not, see <http://www.gnu.org/licenses/>.
18
18
 
19
19
  import { ec as EC } from 'elliptic'
20
20
 
21
- import * as utils from './utils'
21
+ import * as utils from '../utils'
22
22
 
23
23
  const ec = new EC('secp256k1')
24
24
 
@@ -0,0 +1,58 @@
1
+ /*
2
+ Copyright 2018 - 2022 The Alephium Authors
3
+ This file is part of the alephium project.
4
+
5
+ The library is free software: you can redistribute it and/or modify
6
+ it under the terms of the GNU Lesser General Public License as published by
7
+ the Free Software Foundation, either version 3 of the License, or
8
+ (at your option) any later version.
9
+
10
+ The library is distributed in the hope that it will be useful,
11
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ GNU Lesser General Public License for more details.
14
+
15
+ You should have received a copy of the GNU Lesser General Public License
16
+ along with the library. If not, see <http://www.gnu.org/licenses/>.
17
+ */
18
+
19
+ import { TxStatus } from '../api/api-alephium'
20
+ import { Subscription, SubscribeOptions } from '../utils'
21
+
22
+ export class TxStatusSubscription extends Subscription<TxStatus> {
23
+ readonly txId: string
24
+ readonly fromGroup?: number
25
+ readonly toGroup?: number
26
+
27
+ constructor(options: SubscribeOptions<TxStatus>, txId: string, fromGroup?: number, toGroup?: number) {
28
+ super(options)
29
+ this.txId = txId
30
+ this.fromGroup = fromGroup
31
+ this.toGroup = toGroup
32
+
33
+ this.startPolling()
34
+ }
35
+
36
+ override async polling() {
37
+ try {
38
+ const txStatus = await this.provider.transactions.getTransactionsStatus({
39
+ txId: this.txId,
40
+ fromGroup: this.fromGroup,
41
+ toGroup: this.toGroup
42
+ })
43
+
44
+ await this.messageCallback(txStatus)
45
+ } catch (err) {
46
+ await this.errorCallback(err, this)
47
+ }
48
+ }
49
+ }
50
+
51
+ export function subscribeToTxStatus(
52
+ options: SubscribeOptions<TxStatus>,
53
+ txId: string,
54
+ fromGroup?: number,
55
+ toGroup?: number
56
+ ): TxStatusSubscription {
57
+ return new TxStatusSubscription(options, txId, fromGroup, toGroup)
58
+ }
@@ -20,5 +20,5 @@ export * from './address'
20
20
  export * from './bs58'
21
21
  export * from './djb2'
22
22
  export * from './password-crypto'
23
- export * from './transaction'
24
23
  export * from './utils'
24
+ export * from './subscription'