@alephium/web3 0.14.6 → 0.15.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.
@@ -49,3 +49,19 @@ export interface NFTCollectionMetaData {
49
49
  collectionUri: string;
50
50
  totalSupply: Number256;
51
51
  }
52
+ export interface NFTTokenUriMetaData {
53
+ name: string;
54
+ description?: string;
55
+ image: string;
56
+ attributes?: [
57
+ {
58
+ trait_type: string;
59
+ value: string | number | boolean;
60
+ }
61
+ ];
62
+ }
63
+ export interface NFTCollectionUriMetaData {
64
+ name: string;
65
+ description: string;
66
+ image: string;
67
+ }
@@ -1,7 +1,7 @@
1
- import { NamedVals, node, Number256, Token } from '../api';
1
+ import { NamedVals, node, NodeProvider, Number256, Token } from '../api';
2
2
  import { SignDeployContractTxParams, SignDeployContractTxResult, SignExecuteScriptTxParams, SignerProvider, Address } from '../signer';
3
- import { SubscribeOptions, Optional } from '../utils';
4
- import { EventSubscription } from './events';
3
+ import { Optional } from '../utils';
4
+ import { EventSubscribeOptions, EventSubscription } from './events';
5
5
  export type FieldsSig = node.FieldsSig;
6
6
  export type EventSig = node.EventSig;
7
7
  export type FunctionSig = node.FunctionSig;
@@ -51,13 +51,14 @@ type CodeInfo = {
51
51
  codeHashDebug: string;
52
52
  warnings: string[];
53
53
  };
54
- declare class ProjectArtifact {
54
+ export declare class ProjectArtifact {
55
55
  static readonly artifactFileName = ".project.json";
56
56
  fullNodeVersion: string;
57
57
  compilerOptionsUsed: node.CompilerOptions;
58
58
  infos: Map<string, CodeInfo>;
59
59
  static checkCompilerOptionsParameter(compilerOptions: node.CompilerOptions): void;
60
60
  constructor(fullNodeVersion: string, compilerOptionsUsed: node.CompilerOptions, infos: Map<string, CodeInfo>);
61
+ static isCodeChanged(current: ProjectArtifact, previous: ProjectArtifact): boolean;
61
62
  saveToFile(rootPath: string): Promise<void>;
62
63
  needToReCompile(compilerOptions: node.CompilerOptions, sourceInfos: SourceInfo[], fullNodeVersion: string): boolean;
63
64
  static from(rootPath: string): Promise<ProjectArtifact | undefined>;
@@ -284,7 +285,7 @@ export type ContractCreatedEvent = ContractEvent<ContractCreatedEventFields>;
284
285
  export type ContractDestroyedEvent = ContractEvent<ContractDestroyedEventFields>;
285
286
  export declare function decodeContractCreatedEvent(event: node.ContractEvent): Omit<ContractCreatedEvent, 'contractAddress'>;
286
287
  export declare function decodeContractDestroyedEvent(event: node.ContractEvent): Omit<ContractDestroyedEvent, 'contractAddress'>;
287
- export declare function subscribeEventsFromContract<T extends Fields, M extends ContractEvent<T>>(options: SubscribeOptions<M>, address: string, eventIndex: number, decodeFunc: (event: node.ContractEvent) => M, fromCount?: number): EventSubscription;
288
+ export declare function subscribeEventsFromContract<T extends Fields, M extends ContractEvent<T>>(options: EventSubscribeOptions<M>, address: string, eventIndex: number, decodeFunc: (event: node.ContractEvent) => M, fromCount?: number): EventSubscription;
288
289
  export declare function addStdIdToFields<F extends Fields>(contract: Contract, fields: F): F | (F & {
289
290
  __stdInterfaceId: HexString;
290
291
  });
@@ -296,12 +297,14 @@ export declare abstract class ContractInstance {
296
297
  constructor(address: Address);
297
298
  }
298
299
  export declare function fetchContractState<F extends Fields, I extends ContractInstance>(contract: ContractFactory<I, F>, instance: ContractInstance): Promise<ContractState<F>>;
299
- export declare function subscribeContractCreatedEvent(options: SubscribeOptions<ContractCreatedEvent>, fromCount?: number): EventSubscription;
300
- export declare function subscribeContractDestroyedEvent(options: SubscribeOptions<ContractDestroyedEvent>, fromCount?: number): EventSubscription;
300
+ export declare function subscribeContractCreatedEvent(options: EventSubscribeOptions<ContractCreatedEvent>, fromCount?: number): EventSubscription;
301
+ export declare function subscribeContractDestroyedEvent(options: EventSubscribeOptions<ContractDestroyedEvent>, fromCount?: number): EventSubscription;
301
302
  export declare function decodeEvent<F extends Fields, M extends ContractEvent<F>>(contract: Contract, instance: ContractInstance, event: node.ContractEvent, targetEventIndex: number): M;
302
- export declare function subscribeContractEvent<F extends Fields, M extends ContractEvent<F>>(contract: Contract, instance: ContractInstance, options: SubscribeOptions<M>, eventName: string, fromCount?: number): EventSubscription;
303
- export declare function subscribeContractEvents(contract: Contract, instance: ContractInstance, options: SubscribeOptions<ContractEvent<any>>, fromCount?: number): EventSubscription;
303
+ export declare function subscribeContractEvent<F extends Fields, M extends ContractEvent<F>>(contract: Contract, instance: ContractInstance, options: EventSubscribeOptions<M>, eventName: string, fromCount?: number): EventSubscription;
304
+ export declare function subscribeContractEvents(contract: Contract, instance: ContractInstance, options: EventSubscribeOptions<ContractEvent<any>>, fromCount?: number): EventSubscription;
304
305
  export declare function callMethod<I extends ContractInstance, F extends Fields, A extends Arguments, R>(contract: ContractFactory<I, F>, instance: ContractInstance, methodName: string, params: Optional<CallContractParams<A>, 'args'>, getContractByCodeHash?: (codeHash: string) => Contract): Promise<CallContractResult<R>>;
305
306
  export declare function multicallMethods<I extends ContractInstance, F extends Fields>(contract: ContractFactory<I, F>, instance: ContractInstance, calls: Record<string, Optional<CallContractParams<any>, 'args'>>, getContractByCodeHash?: (codeHash: string) => Contract): Promise<Record<string, CallContractResult<any>>>;
306
307
  export declare function getContractEventsCurrentCount(contractAddress: Address): Promise<number>;
308
+ export declare const getContractIdFromTxId: (nodeProvider: NodeProvider, txId: string, groupIndex: number) => Promise<HexString>;
309
+ export declare const getTokenIdFromTxId: (nodeProvider: NodeProvider, txId: string, groupIndex: number) => Promise<HexString>;
307
310
  export {};
@@ -43,7 +43,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
43
43
  return (mod && mod.__esModule) ? mod : { "default": mod };
44
44
  };
45
45
  Object.defineProperty(exports, "__esModule", { value: true });
46
- exports.getContractEventsCurrentCount = exports.multicallMethods = exports.callMethod = exports.subscribeContractEvents = exports.subscribeContractEvent = exports.decodeEvent = exports.subscribeContractDestroyedEvent = exports.subscribeContractCreatedEvent = exports.fetchContractState = exports.ContractInstance = exports.testMethod = exports.addStdIdToFields = exports.subscribeEventsFromContract = exports.decodeContractDestroyedEvent = exports.decodeContractCreatedEvent = exports.DestroyContractEventAddress = exports.CreateContractEventAddress = exports.ExecutableScript = exports.ContractFactory = exports.randomTxId = exports.toApiVals = exports.Script = exports.Contract = exports.Artifact = exports.Project = exports.DEFAULT_COMPILER_OPTIONS = exports.DEFAULT_NODE_COMPILER_OPTIONS = exports.StdIdFieldName = void 0;
46
+ exports.getTokenIdFromTxId = exports.getContractIdFromTxId = exports.getContractEventsCurrentCount = exports.multicallMethods = exports.callMethod = exports.subscribeContractEvents = exports.subscribeContractEvent = exports.decodeEvent = exports.subscribeContractDestroyedEvent = exports.subscribeContractCreatedEvent = exports.fetchContractState = exports.ContractInstance = exports.testMethod = exports.addStdIdToFields = exports.subscribeEventsFromContract = exports.decodeContractDestroyedEvent = exports.decodeContractCreatedEvent = exports.DestroyContractEventAddress = exports.CreateContractEventAddress = exports.ExecutableScript = exports.ContractFactory = exports.randomTxId = exports.toApiVals = exports.Script = exports.Contract = exports.Artifact = exports.Project = exports.ProjectArtifact = exports.DEFAULT_COMPILER_OPTIONS = exports.DEFAULT_NODE_COMPILER_OPTIONS = exports.StdIdFieldName = void 0;
47
47
  const buffer_1 = require("buffer/");
48
48
  const fs_1 = __importDefault(require("fs"));
49
49
  const fs_2 = require("fs");
@@ -54,6 +54,7 @@ const global_1 = require("../global");
54
54
  const path = __importStar(require("path"));
55
55
  const events_1 = require("./events");
56
56
  const constants_1 = require("../constants");
57
+ const blake = __importStar(require("blakejs"));
57
58
  const crypto = new utils_1.WebCrypto();
58
59
  exports.StdIdFieldName = '__stdInterfaceId';
59
60
  var SourceKind;
@@ -140,6 +141,18 @@ class ProjectArtifact {
140
141
  this.compilerOptionsUsed = compilerOptionsUsed;
141
142
  this.infos = infos;
142
143
  }
144
+ static isCodeChanged(current, previous) {
145
+ if (current.infos.size !== previous.infos.size) {
146
+ return true;
147
+ }
148
+ for (const [name, codeInfo] of current.infos) {
149
+ const prevCodeInfo = previous.infos.get(name);
150
+ if (prevCodeInfo?.codeHashDebug !== codeInfo.codeHashDebug) {
151
+ return true;
152
+ }
153
+ }
154
+ return false;
155
+ }
143
156
  async saveToFile(rootPath) {
144
157
  const filepath = path.join(rootPath, ProjectArtifact.artifactFileName);
145
158
  const artifact = {
@@ -192,6 +205,7 @@ class ProjectArtifact {
192
205
  }
193
206
  }
194
207
  }
208
+ exports.ProjectArtifact = ProjectArtifact;
195
209
  ProjectArtifact.artifactFileName = '.project.json';
196
210
  class Project {
197
211
  static buildProjectArtifact(fullNodeVersion, sourceInfos, contracts, scripts, compilerOptions) {
@@ -1002,7 +1016,8 @@ function subscribeEventsFromContract(options, address, eventIndex, decodeFunc, f
1002
1016
  const opt = {
1003
1017
  pollingInterval: options.pollingInterval,
1004
1018
  messageCallback: messageCallback,
1005
- errorCallback: errorCallback
1019
+ errorCallback: errorCallback,
1020
+ onEventCountChanged: options.onEventCountChanged
1006
1021
  };
1007
1022
  return (0, events_1.subscribeToEvents)(opt, address, fromCount);
1008
1023
  }
@@ -1103,7 +1118,8 @@ function subscribeContractEvents(contract, instance, options, fromCount) {
1103
1118
  const opt = {
1104
1119
  pollingInterval: options.pollingInterval,
1105
1120
  messageCallback: messageCallback,
1106
- errorCallback: errorCallback
1121
+ errorCallback: errorCallback,
1122
+ onEventCountChanged: options.onEventCountChanged
1107
1123
  };
1108
1124
  return (0, events_1.subscribeToEvents)(opt, instance.address, fromCount);
1109
1125
  }
@@ -1147,3 +1163,17 @@ async function getContractEventsCurrentCount(contractAddress) {
1147
1163
  });
1148
1164
  }
1149
1165
  exports.getContractEventsCurrentCount = getContractEventsCurrentCount;
1166
+ // This function only works in the simple case where a single non-subcontract is created in the tx
1167
+ const getContractIdFromTxId = async (nodeProvider, txId, groupIndex) => {
1168
+ const txDetails = await nodeProvider.transactions.getTransactionsDetailsTxid(txId, {
1169
+ fromGroup: groupIndex,
1170
+ toGroup: groupIndex
1171
+ });
1172
+ const outputIndex = txDetails.unsigned.fixedOutputs.length;
1173
+ const hex = txId + outputIndex.toString(16).padStart(8, '0');
1174
+ const hashHex = (0, utils_1.binToHex)(blake.blake2b((0, utils_1.hexToBinUnsafe)(hex), undefined, 32));
1175
+ return hashHex.slice(0, 62) + groupIndex.toString(16).padStart(2, '0');
1176
+ };
1177
+ exports.getContractIdFromTxId = getContractIdFromTxId;
1178
+ // This function only works in the simple case where a single non-subcontract is created in the tx
1179
+ exports.getTokenIdFromTxId = exports.getContractIdFromTxId;
@@ -1,11 +1,15 @@
1
1
  import { node } from '../api';
2
2
  import { Subscription, SubscribeOptions } from '../utils';
3
+ export interface EventSubscribeOptions<Message> extends SubscribeOptions<Message> {
4
+ onEventCountChanged?: (eventCount: number) => Promise<void>;
5
+ }
3
6
  export declare class EventSubscription extends Subscription<node.ContractEvent> {
4
7
  readonly contractAddress: string;
5
8
  private fromCount;
6
- constructor(options: SubscribeOptions<node.ContractEvent>, contractAddress: string, fromCount?: number);
9
+ private onEventCountChanged?;
10
+ constructor(options: EventSubscribeOptions<node.ContractEvent>, contractAddress: string, fromCount?: number);
7
11
  startPolling(): void;
8
12
  currentEventCount(): number;
9
13
  polling(): Promise<void>;
10
14
  }
11
- export declare function subscribeToEvents(options: SubscribeOptions<node.ContractEvent>, contractAddress: string, fromCount?: number): EventSubscription;
15
+ export declare function subscribeToEvents(options: EventSubscribeOptions<node.ContractEvent>, contractAddress: string, fromCount?: number): EventSubscription;
@@ -25,6 +25,7 @@ class EventSubscription extends utils_1.Subscription {
25
25
  super(options);
26
26
  this.contractAddress = contractAddress;
27
27
  this.fromCount = typeof fromCount === 'undefined' ? 0 : fromCount;
28
+ this.onEventCountChanged = options.onEventCountChanged;
28
29
  this.startPolling();
29
30
  }
30
31
  startPolling() {
@@ -51,6 +52,9 @@ class EventSubscription extends utils_1.Subscription {
51
52
  const promises = events.events.map((event) => this.messageCallback(event));
52
53
  await Promise.all(promises);
53
54
  this.fromCount = events.nextStart;
55
+ if (this.onEventCountChanged !== undefined) {
56
+ await this.onEventCountChanged(this.fromCount);
57
+ }
54
58
  await this.polling();
55
59
  }
56
60
  catch (err) {
@@ -1,24 +1,9 @@
1
1
  import 'cross-fetch/polyfill';
2
- export interface NFTMetadata {
3
- name: string;
4
- description?: string;
5
- image: string;
6
- attributes?: [
7
- {
8
- trait_type: string;
9
- value: string | number | boolean;
10
- }
11
- ];
12
- }
13
- export interface NFTCollectionMetadata {
14
- name: string;
15
- description: string;
16
- image: string;
17
- }
18
- export declare const validNFTMetadataFields: string[];
19
- export declare const validNFTMetadataAttributesFields: string[];
20
- export declare const validNFTMetadataAttributeTypes: string[];
21
- export declare const validNFTCollectionMetadataFields: string[];
22
- export declare function validateNFTMetadata(metadata: any): NFTMetadata;
23
- export declare function validateNFTCollectionMetadata(metadata: any): NFTCollectionMetadata;
24
- export declare function validateEnumerableNFTBaseUri(nftBaseUri: string, maxSupply: number): Promise<NFTMetadata[]>;
2
+ import { NFTCollectionUriMetaData, NFTTokenUriMetaData } from '../api';
3
+ export declare const validNFTTokenUriMetaDataFields: string[];
4
+ export declare const validNFTTokenUriMetaDataAttributesFields: string[];
5
+ export declare const validNFTUriMetaDataAttributeTypes: string[];
6
+ export declare const validNFTCollectionUriMetaDataFields: string[];
7
+ export declare function validateNFTTokenUriMetaData(metadata: any): NFTTokenUriMetaData;
8
+ export declare function validateNFTCollectionUriMetaData(metadata: any): NFTCollectionUriMetaData;
9
+ export declare function validateNFTBaseUri(nftBaseUri: string, maxSupply: number): Promise<NFTTokenUriMetaData[]>;
@@ -17,31 +17,31 @@ You should have received a copy of the GNU Lesser General Public License
17
17
  along with the library. If not, see <http://www.gnu.org/licenses/>.
18
18
  */
19
19
  Object.defineProperty(exports, "__esModule", { value: true });
20
- exports.validateEnumerableNFTBaseUri = exports.validateNFTCollectionMetadata = exports.validateNFTMetadata = exports.validNFTCollectionMetadataFields = exports.validNFTMetadataAttributeTypes = exports.validNFTMetadataAttributesFields = exports.validNFTMetadataFields = void 0;
20
+ exports.validateNFTBaseUri = exports.validateNFTCollectionUriMetaData = exports.validateNFTTokenUriMetaData = exports.validNFTCollectionUriMetaDataFields = exports.validNFTUriMetaDataAttributeTypes = exports.validNFTTokenUriMetaDataAttributesFields = exports.validNFTTokenUriMetaDataFields = void 0;
21
21
  // JSON Schema for the NFT metadata, which is pointed to by the value
22
22
  // returned from the `getTokenUri` method of the NFT contract
23
23
  require("cross-fetch/polyfill");
24
- exports.validNFTMetadataFields = ['name', 'description', 'image', 'attributes'];
25
- exports.validNFTMetadataAttributesFields = ['trait_type', 'value'];
26
- exports.validNFTMetadataAttributeTypes = ['string', 'number', 'boolean'];
27
- exports.validNFTCollectionMetadataFields = ['name', 'description', 'image'];
28
- function validateNFTMetadata(metadata) {
24
+ exports.validNFTTokenUriMetaDataFields = ['name', 'description', 'image', 'attributes'];
25
+ exports.validNFTTokenUriMetaDataAttributesFields = ['trait_type', 'value'];
26
+ exports.validNFTUriMetaDataAttributeTypes = ['string', 'number', 'boolean'];
27
+ exports.validNFTCollectionUriMetaDataFields = ['name', 'description', 'image'];
28
+ function validateNFTTokenUriMetaData(metadata) {
29
29
  Object.keys(metadata).forEach((key) => {
30
- if (!exports.validNFTMetadataFields.includes(key)) {
31
- throw new Error(`Invalid field ${key}, only ${exports.validNFTMetadataFields} are allowed`);
30
+ if (!exports.validNFTTokenUriMetaDataFields.includes(key)) {
31
+ throw new Error(`Invalid field ${key}, only ${exports.validNFTTokenUriMetaDataFields} are allowed`);
32
32
  }
33
33
  });
34
34
  const name = validateNonEmptyString(metadata, 'name');
35
35
  const description = validateNonEmptyStringIfExists(metadata, 'description');
36
36
  const image = validateNonEmptyString(metadata, 'image');
37
- const attributes = validateNFTMetadataAttributes(metadata['attributes']);
37
+ const attributes = validateNFTTokenUriMetaDataAttributes(metadata['attributes']);
38
38
  return { name, description, image, attributes };
39
39
  }
40
- exports.validateNFTMetadata = validateNFTMetadata;
41
- function validateNFTCollectionMetadata(metadata) {
40
+ exports.validateNFTTokenUriMetaData = validateNFTTokenUriMetaData;
41
+ function validateNFTCollectionUriMetaData(metadata) {
42
42
  Object.keys(metadata).forEach((key) => {
43
- if (!exports.validNFTCollectionMetadataFields.includes(key)) {
44
- throw new Error(`Invalid field ${key}, only ${exports.validNFTCollectionMetadataFields} are allowed`);
43
+ if (!exports.validNFTCollectionUriMetaDataFields.includes(key)) {
44
+ throw new Error(`Invalid field ${key}, only ${exports.validNFTCollectionUriMetaDataFields} are allowed`);
45
45
  }
46
46
  });
47
47
  const name = validateNonEmptyString(metadata, 'name');
@@ -49,13 +49,13 @@ function validateNFTCollectionMetadata(metadata) {
49
49
  const image = validateNonEmptyString(metadata, 'image');
50
50
  return { name, description, image };
51
51
  }
52
- exports.validateNFTCollectionMetadata = validateNFTCollectionMetadata;
53
- async function validateEnumerableNFTBaseUri(nftBaseUri, maxSupply) {
52
+ exports.validateNFTCollectionUriMetaData = validateNFTCollectionUriMetaData;
53
+ async function validateNFTBaseUri(nftBaseUri, maxSupply) {
54
54
  if (isInteger(maxSupply) && maxSupply > 0) {
55
55
  const nftMetadataz = [];
56
56
  for (let i = 0; i < maxSupply; i++) {
57
57
  const nftMetadata = await fetchNFTMetadata(nftBaseUri, i);
58
- const validatedNFTMetadata = validateNFTMetadata(nftMetadata);
58
+ const validatedNFTMetadata = validateNFTTokenUriMetaData(nftMetadata);
59
59
  nftMetadataz.push(validatedNFTMetadata);
60
60
  }
61
61
  return nftMetadataz;
@@ -64,8 +64,8 @@ async function validateEnumerableNFTBaseUri(nftBaseUri, maxSupply) {
64
64
  throw new Error('maxSupply should be a positive integer');
65
65
  }
66
66
  }
67
- exports.validateEnumerableNFTBaseUri = validateEnumerableNFTBaseUri;
68
- function validateNFTMetadataAttributes(attributes) {
67
+ exports.validateNFTBaseUri = validateNFTBaseUri;
68
+ function validateNFTTokenUriMetaDataAttributes(attributes) {
69
69
  if (!!attributes) {
70
70
  if (!Array.isArray(attributes)) {
71
71
  throw new Error(`Field 'attributes' should be an array`);
@@ -75,8 +75,8 @@ function validateNFTMetadataAttributes(attributes) {
75
75
  throw new Error(`Field 'attributes' should be an array of objects`);
76
76
  }
77
77
  Object.keys(item).forEach((key) => {
78
- if (!exports.validNFTMetadataAttributesFields.includes(key)) {
79
- throw new Error(`Invalid field ${key} for attributes, only ${exports.validNFTMetadataAttributesFields} are allowed`);
78
+ if (!exports.validNFTTokenUriMetaDataAttributesFields.includes(key)) {
79
+ throw new Error(`Invalid field ${key} for attributes, only ${exports.validNFTTokenUriMetaDataAttributesFields} are allowed`);
80
80
  }
81
81
  });
82
82
  validateNonEmptyString(item, 'trait_type');
@@ -5,7 +5,8 @@ export declare class TxStatusSubscription extends Subscription<TxStatus> {
5
5
  readonly txId: string;
6
6
  readonly fromGroup?: number;
7
7
  readonly toGroup?: number;
8
- constructor(options: SubscribeOptions<TxStatus>, txId: string, fromGroup?: number, toGroup?: number);
8
+ readonly confirmations: number;
9
+ constructor(options: SubscribeOptions<TxStatus>, txId: string, fromGroup?: number, toGroup?: number, confirmations?: number);
9
10
  polling(): Promise<void>;
10
11
  }
11
- export declare function subscribeToTxStatus(options: SubscribeOptions<TxStatus>, txId: string, fromGroup?: number, toGroup?: number): TxStatusSubscription;
12
+ export declare function subscribeToTxStatus(options: SubscribeOptions<TxStatus>, txId: string, fromGroup?: number, toGroup?: number, confirmations?: number): TxStatusSubscription;
@@ -21,11 +21,12 @@ exports.subscribeToTxStatus = exports.TxStatusSubscription = void 0;
21
21
  const __1 = require("..");
22
22
  const utils_1 = require("../utils");
23
23
  class TxStatusSubscription extends utils_1.Subscription {
24
- constructor(options, txId, fromGroup, toGroup) {
24
+ constructor(options, txId, fromGroup, toGroup, confirmations) {
25
25
  super(options);
26
26
  this.txId = txId;
27
27
  this.fromGroup = fromGroup;
28
28
  this.toGroup = toGroup;
29
+ this.confirmations = confirmations ?? 1;
29
30
  this.startPolling();
30
31
  }
31
32
  async polling() {
@@ -36,6 +37,9 @@ class TxStatusSubscription extends utils_1.Subscription {
36
37
  toGroup: this.toGroup
37
38
  });
38
39
  await this.messageCallback(txStatus);
40
+ if (txStatus.type === 'Confirmed' && txStatus.chainConfirmations >= this.confirmations) {
41
+ this.unsubscribe();
42
+ }
39
43
  }
40
44
  catch (err) {
41
45
  await this.errorCallback(err, this);
@@ -43,7 +47,7 @@ class TxStatusSubscription extends utils_1.Subscription {
43
47
  }
44
48
  }
45
49
  exports.TxStatusSubscription = TxStatusSubscription;
46
- function subscribeToTxStatus(options, txId, fromGroup, toGroup) {
47
- return new TxStatusSubscription(options, txId, fromGroup, toGroup);
50
+ function subscribeToTxStatus(options, txId, fromGroup, toGroup, confirmations) {
51
+ return new TxStatusSubscription(options, txId, fromGroup, toGroup, confirmations);
48
52
  }
49
53
  exports.subscribeToTxStatus = subscribeToTxStatus;
@@ -16,6 +16,7 @@ export declare abstract class Subscription<Message> {
16
16
  constructor(options: SubscribeOptions<Message>);
17
17
  startPolling(): void;
18
18
  unsubscribe(): void;
19
+ isCancelled(): boolean;
19
20
  abstract polling(): Promise<void>;
20
21
  }
21
22
  export {};
@@ -47,5 +47,8 @@ class Subscription {
47
47
  clearTimeout(this.task);
48
48
  }
49
49
  }
50
+ isCancelled() {
51
+ return this.cancelled;
52
+ }
50
53
  }
51
54
  exports.Subscription = Subscription;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@alephium/web3",
3
- "version": "0.14.6",
3
+ "version": "0.15.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",
package/src/api/types.ts CHANGED
@@ -286,3 +286,21 @@ export interface NFTCollectionMetaData {
286
286
  collectionUri: string
287
287
  totalSupply: Number256
288
288
  }
289
+
290
+ export interface NFTTokenUriMetaData {
291
+ name: string
292
+ description?: string
293
+ image: string
294
+ attributes?: [
295
+ {
296
+ trait_type: string
297
+ value: string | number | boolean
298
+ }
299
+ ]
300
+ }
301
+
302
+ export interface NFTCollectionUriMetaData {
303
+ name: string
304
+ description: string
305
+ image: string
306
+ }
@@ -47,19 +47,20 @@ import {
47
47
  bs58,
48
48
  binToHex,
49
49
  contractIdFromAddress,
50
- SubscribeOptions,
51
50
  Subscription,
52
51
  assertType,
53
52
  Eq,
54
53
  Optional,
55
54
  groupOfAddress,
56
55
  addressFromContractId,
57
- WebCrypto
56
+ WebCrypto,
57
+ hexToBinUnsafe
58
58
  } from '../utils'
59
59
  import { getCurrentNodeProvider } from '../global'
60
60
  import * as path from 'path'
61
- import { EventSubscription, subscribeToEvents } from './events'
61
+ import { EventSubscribeOptions, EventSubscription, subscribeToEvents } from './events'
62
62
  import { ONE_ALPH } from '../constants'
63
+ import * as blake from 'blakejs'
63
64
 
64
65
  const crypto = new WebCrypto()
65
66
 
@@ -187,7 +188,7 @@ type CodeInfo = {
187
188
  warnings: string[]
188
189
  }
189
190
 
190
- class ProjectArtifact {
191
+ export class ProjectArtifact {
191
192
  static readonly artifactFileName = '.project.json'
192
193
 
193
194
  fullNodeVersion: string
@@ -212,6 +213,19 @@ class ProjectArtifact {
212
213
  this.infos = infos
213
214
  }
214
215
 
216
+ static isCodeChanged(current: ProjectArtifact, previous: ProjectArtifact): boolean {
217
+ if (current.infos.size !== previous.infos.size) {
218
+ return true
219
+ }
220
+ for (const [name, codeInfo] of current.infos) {
221
+ const prevCodeInfo = previous.infos.get(name)
222
+ if (prevCodeInfo?.codeHashDebug !== codeInfo.codeHashDebug) {
223
+ return true
224
+ }
225
+ }
226
+ return false
227
+ }
228
+
215
229
  async saveToFile(rootPath: string): Promise<void> {
216
230
  const filepath = path.join(rootPath, ProjectArtifact.artifactFileName)
217
231
  const artifact = {
@@ -1527,7 +1541,7 @@ export function decodeContractDestroyedEvent(
1527
1541
  }
1528
1542
 
1529
1543
  export function subscribeEventsFromContract<T extends Fields, M extends ContractEvent<T>>(
1530
- options: SubscribeOptions<M>,
1544
+ options: EventSubscribeOptions<M>,
1531
1545
  address: string,
1532
1546
  eventIndex: number,
1533
1547
  decodeFunc: (event: node.ContractEvent) => M,
@@ -1543,10 +1557,11 @@ export function subscribeEventsFromContract<T extends Fields, M extends Contract
1543
1557
  const errorCallback = (err: any, subscription: Subscription<node.ContractEvent>): Promise<void> => {
1544
1558
  return options.errorCallback(err, subscription as unknown as Subscription<M>)
1545
1559
  }
1546
- const opt: SubscribeOptions<node.ContractEvent> = {
1560
+ const opt: EventSubscribeOptions<node.ContractEvent> = {
1547
1561
  pollingInterval: options.pollingInterval,
1548
1562
  messageCallback: messageCallback,
1549
- errorCallback: errorCallback
1563
+ errorCallback: errorCallback,
1564
+ onEventCountChanged: options.onEventCountChanged
1550
1565
  }
1551
1566
  return subscribeToEvents(opt, address, fromCount)
1552
1567
  }
@@ -1607,7 +1622,7 @@ export async function fetchContractState<F extends Fields, I extends ContractIns
1607
1622
  }
1608
1623
 
1609
1624
  export function subscribeContractCreatedEvent(
1610
- options: SubscribeOptions<ContractCreatedEvent>,
1625
+ options: EventSubscribeOptions<ContractCreatedEvent>,
1611
1626
  fromCount?: number
1612
1627
  ): EventSubscription {
1613
1628
  return subscribeEventsFromContract(
@@ -1625,7 +1640,7 @@ export function subscribeContractCreatedEvent(
1625
1640
  }
1626
1641
 
1627
1642
  export function subscribeContractDestroyedEvent(
1628
- options: SubscribeOptions<ContractDestroyedEvent>,
1643
+ options: EventSubscribeOptions<ContractDestroyedEvent>,
1629
1644
  fromCount?: number
1630
1645
  ): EventSubscription {
1631
1646
  return subscribeEventsFromContract(
@@ -1671,7 +1686,7 @@ export function decodeEvent<F extends Fields, M extends ContractEvent<F>>(
1671
1686
  export function subscribeContractEvent<F extends Fields, M extends ContractEvent<F>>(
1672
1687
  contract: Contract,
1673
1688
  instance: ContractInstance,
1674
- options: SubscribeOptions<M>,
1689
+ options: EventSubscribeOptions<M>,
1675
1690
  eventName: string,
1676
1691
  fromCount?: number
1677
1692
  ): EventSubscription {
@@ -1688,7 +1703,7 @@ export function subscribeContractEvent<F extends Fields, M extends ContractEvent
1688
1703
  export function subscribeContractEvents(
1689
1704
  contract: Contract,
1690
1705
  instance: ContractInstance,
1691
- options: SubscribeOptions<ContractEvent<any>>,
1706
+ options: EventSubscribeOptions<ContractEvent<any>>,
1692
1707
  fromCount?: number
1693
1708
  ): EventSubscription {
1694
1709
  const messageCallback = (event: node.ContractEvent): Promise<void> => {
@@ -1700,10 +1715,11 @@ export function subscribeContractEvents(
1700
1715
  const errorCallback = (err: any, subscription: Subscription<node.ContractEvent>): Promise<void> => {
1701
1716
  return options.errorCallback(err, subscription as unknown as Subscription<ContractEvent<any>>)
1702
1717
  }
1703
- const opt: SubscribeOptions<node.ContractEvent> = {
1718
+ const opt: EventSubscribeOptions<node.ContractEvent> = {
1704
1719
  pollingInterval: options.pollingInterval,
1705
1720
  messageCallback: messageCallback,
1706
- errorCallback: errorCallback
1721
+ errorCallback: errorCallback,
1722
+ onEventCountChanged: options.onEventCountChanged
1707
1723
  }
1708
1724
  return subscribeToEvents(opt, instance.address, fromCount)
1709
1725
  }
@@ -1772,3 +1788,22 @@ export async function getContractEventsCurrentCount(contractAddress: Address): P
1772
1788
  throw error
1773
1789
  })
1774
1790
  }
1791
+
1792
+ // This function only works in the simple case where a single non-subcontract is created in the tx
1793
+ export const getContractIdFromTxId = async (
1794
+ nodeProvider: NodeProvider,
1795
+ txId: string,
1796
+ groupIndex: number
1797
+ ): Promise<HexString> => {
1798
+ const txDetails = await nodeProvider.transactions.getTransactionsDetailsTxid(txId, {
1799
+ fromGroup: groupIndex,
1800
+ toGroup: groupIndex
1801
+ })
1802
+ const outputIndex = txDetails.unsigned.fixedOutputs.length
1803
+ const hex = txId + outputIndex.toString(16).padStart(8, '0')
1804
+ const hashHex = binToHex(blake.blake2b(hexToBinUnsafe(hex), undefined, 32))
1805
+ return hashHex.slice(0, 62) + groupIndex.toString(16).padStart(2, '0')
1806
+ }
1807
+
1808
+ // This function only works in the simple case where a single non-subcontract is created in the tx
1809
+ export const getTokenIdFromTxId = getContractIdFromTxId
@@ -20,14 +20,20 @@ import { web3 } from '..'
20
20
  import { node } from '../api'
21
21
  import { Subscription, SubscribeOptions } from '../utils'
22
22
 
23
+ export interface EventSubscribeOptions<Message> extends SubscribeOptions<Message> {
24
+ onEventCountChanged?: (eventCount: number) => Promise<void>
25
+ }
26
+
23
27
  export class EventSubscription extends Subscription<node.ContractEvent> {
24
28
  readonly contractAddress: string
25
29
  private fromCount: number
30
+ private onEventCountChanged?: (eventCount: number) => Promise<void>
26
31
 
27
- constructor(options: SubscribeOptions<node.ContractEvent>, contractAddress: string, fromCount?: number) {
32
+ constructor(options: EventSubscribeOptions<node.ContractEvent>, contractAddress: string, fromCount?: number) {
28
33
  super(options)
29
34
  this.contractAddress = contractAddress
30
35
  this.fromCount = typeof fromCount === 'undefined' ? 0 : fromCount
36
+ this.onEventCountChanged = options.onEventCountChanged
31
37
 
32
38
  this.startPolling()
33
39
  }
@@ -60,6 +66,11 @@ export class EventSubscription extends Subscription<node.ContractEvent> {
60
66
  const promises = events.events.map((event) => this.messageCallback(event))
61
67
  await Promise.all(promises)
62
68
  this.fromCount = events.nextStart
69
+
70
+ if (this.onEventCountChanged !== undefined) {
71
+ await this.onEventCountChanged(this.fromCount)
72
+ }
73
+
63
74
  await this.polling()
64
75
  } catch (err) {
65
76
  await this.errorCallback(err, this)
@@ -68,7 +79,7 @@ export class EventSubscription extends Subscription<node.ContractEvent> {
68
79
  }
69
80
 
70
81
  export function subscribeToEvents(
71
- options: SubscribeOptions<node.ContractEvent>,
82
+ options: EventSubscribeOptions<node.ContractEvent>,
72
83
  contractAddress: string,
73
84
  fromCount?: number
74
85
  ): EventSubscription {