@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.
- package/dist/alephium-web3.min.js +1 -1
- package/dist/alephium-web3.min.js.map +1 -1
- package/dist/src/api/types.d.ts +16 -0
- package/dist/src/contract/contract.d.ts +12 -9
- package/dist/src/contract/contract.js +33 -3
- package/dist/src/contract/events.d.ts +6 -2
- package/dist/src/contract/events.js +4 -0
- package/dist/src/token/nft.d.ts +8 -23
- package/dist/src/token/nft.js +20 -20
- package/dist/src/transaction/status.d.ts +3 -2
- package/dist/src/transaction/status.js +7 -3
- package/dist/src/utils/subscription.d.ts +1 -0
- package/dist/src/utils/subscription.js +3 -0
- package/package.json +1 -1
- package/src/api/types.ts +18 -0
- package/src/contract/contract.ts +48 -13
- package/src/contract/events.ts +13 -2
- package/src/token/nft.ts +21 -39
- package/src/transaction/status.ts +15 -3
- package/src/utils/subscription.ts +4 -0
package/dist/src/api/types.d.ts
CHANGED
|
@@ -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 {
|
|
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:
|
|
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:
|
|
300
|
-
export declare function subscribeContractDestroyedEvent(options:
|
|
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:
|
|
303
|
-
export declare function subscribeContractEvents(contract: Contract, instance: ContractInstance, options:
|
|
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
|
-
|
|
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:
|
|
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) {
|
package/dist/src/token/nft.d.ts
CHANGED
|
@@ -1,24 +1,9 @@
|
|
|
1
1
|
import 'cross-fetch/polyfill';
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
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[]>;
|
package/dist/src/token/nft.js
CHANGED
|
@@ -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.
|
|
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.
|
|
25
|
-
exports.
|
|
26
|
-
exports.
|
|
27
|
-
exports.
|
|
28
|
-
function
|
|
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.
|
|
31
|
-
throw new Error(`Invalid field ${key}, only ${exports.
|
|
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 =
|
|
37
|
+
const attributes = validateNFTTokenUriMetaDataAttributes(metadata['attributes']);
|
|
38
38
|
return { name, description, image, attributes };
|
|
39
39
|
}
|
|
40
|
-
exports.
|
|
41
|
-
function
|
|
40
|
+
exports.validateNFTTokenUriMetaData = validateNFTTokenUriMetaData;
|
|
41
|
+
function validateNFTCollectionUriMetaData(metadata) {
|
|
42
42
|
Object.keys(metadata).forEach((key) => {
|
|
43
|
-
if (!exports.
|
|
44
|
-
throw new Error(`Invalid field ${key}, only ${exports.
|
|
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.
|
|
53
|
-
async function
|
|
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 =
|
|
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.
|
|
68
|
-
function
|
|
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.
|
|
79
|
-
throw new Error(`Invalid field ${key} for attributes, only ${exports.
|
|
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
|
-
|
|
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;
|
package/package.json
CHANGED
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
|
+
}
|
package/src/contract/contract.ts
CHANGED
|
@@ -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:
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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
|
package/src/contract/events.ts
CHANGED
|
@@ -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:
|
|
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:
|
|
82
|
+
options: EventSubscribeOptions<node.ContractEvent>,
|
|
72
83
|
contractAddress: string,
|
|
73
84
|
fromCount?: number
|
|
74
85
|
): EventSubscription {
|