@tezos-x/octez.js-tzip16 0.9.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 (37) hide show
  1. package/README.md +68 -0
  2. package/dist/lib/composer.js +17 -0
  3. package/dist/lib/errors.js +138 -0
  4. package/dist/lib/handlers/http-handler.js +31 -0
  5. package/dist/lib/handlers/ipfs-handler.js +32 -0
  6. package/dist/lib/handlers/tezos-storage-handler.js +62 -0
  7. package/dist/lib/metadata-interface.js +8 -0
  8. package/dist/lib/metadata-provider.js +68 -0
  9. package/dist/lib/octez.js-tzip16.js +36 -0
  10. package/dist/lib/tzip16-contract-abstraction.js +174 -0
  11. package/dist/lib/tzip16-extension.js +22 -0
  12. package/dist/lib/tzip16-utils.js +7 -0
  13. package/dist/lib/version.js +8 -0
  14. package/dist/lib/viewKind/interface.js +2 -0
  15. package/dist/lib/viewKind/michelson-storage-view.js +177 -0
  16. package/dist/lib/viewKind/viewFactory.js +27 -0
  17. package/dist/octez.js-tzip16.es6.js +687 -0
  18. package/dist/octez.js-tzip16.es6.js.map +1 -0
  19. package/dist/octez.js-tzip16.umd.js +711 -0
  20. package/dist/octez.js-tzip16.umd.js.map +1 -0
  21. package/dist/types/composer.d.ts +9 -0
  22. package/dist/types/errors.d.ts +80 -0
  23. package/dist/types/handlers/http-handler.d.ts +8 -0
  24. package/dist/types/handlers/ipfs-handler.d.ts +9 -0
  25. package/dist/types/handlers/tezos-storage-handler.d.ts +15 -0
  26. package/dist/types/metadata-interface.d.ts +68 -0
  27. package/dist/types/metadata-provider.d.ts +37 -0
  28. package/dist/types/octez.js-tzip16.d.ts +18 -0
  29. package/dist/types/tzip16-contract-abstraction.d.ts +42 -0
  30. package/dist/types/tzip16-extension.d.ts +8 -0
  31. package/dist/types/tzip16-utils.d.ts +1 -0
  32. package/dist/types/version.d.ts +4 -0
  33. package/dist/types/viewKind/interface.d.ts +3 -0
  34. package/dist/types/viewKind/michelson-storage-view.d.ts +32 -0
  35. package/dist/types/viewKind/viewFactory.d.ts +9 -0
  36. package/package.json +104 -0
  37. package/signature.json +439 -0
package/README.md ADDED
@@ -0,0 +1,68 @@
1
+ # octez.js TZIP-016 package
2
+
3
+ *Documentation can be found [here](https://octez.js.io/docs/metadata-tzip16/)*
4
+ *TypeDoc style documentation is available on-line [here](https://octez.js.io/typedoc/modules/_octez.js_tzip16.html)*
5
+
6
+ **Maintained by [Nomadic Labs](https://www.nomadic-labs.com/).**
7
+
8
+ `@tezos-x/octez.js-tzip16` is an npm package that provides developers with TZIP-016 functionality for octez.js. TZIP-016 is a standard for encoding access to smart contract metadata either on-chain or off-chain. The `@tezos-x/octez.js-tzip16` package allows developers to retrieve the metadata associated with a smart contract and execute the off-chain views found in the metadata.
9
+
10
+ ## General Information
11
+
12
+ Contract metadata gathers valuable information about the contract that is not directly used for its operation. According to TZIP-016, a contract with metadata must include in its storage a big_map named `%metadata` of the following type: `(big_map %metadata string bytes)`. The big_map must have an empty string as a key where its value is a byte-encoded URI representing the metadata location. Contract metadata can be located on-chain or off-chain (web services or IPFS). Please refer to the following link for complete documentation on [TZIP-016](https://gitlab.com/tezos/tzip/-/blob/master/proposals/tzip-16/tzip-16.md#introduction).
13
+
14
+ When using the `@tezos-x/octez.js-tzip16` package, developers can retrieve metadata of a contract based on its address. The underlying steps performed by octez.js are to find the URI in the contract storage, decode it, extract the metadata depending on the protocol (tezos-storage, HTTP(S) or IPFS), perform an integrity check if the URI contains a sha256 hash, and return the metadata to the user.
15
+
16
+ Another functionality of the `@tezos-x/octez.js-tzip16` package allows executing off-chain views. If a contract contains views in its metadata, octez.js builds an ordinary JavaScript object with methods corresponding to the views name.
17
+
18
+ ## Install
19
+
20
+ The package can be used to extend the well-known octez.js contract abstraction. The `@tezos-x/octez.js-tzip16` and the `@tezos-x/octez.js` packages need to be installed as follows:
21
+
22
+ ```
23
+ npm i --save @tezos-x/octez.js-tzip16
24
+ npm i --save @tezos-x/octez.js
25
+ ```
26
+
27
+ ## Usage
28
+
29
+ **Create an instance of the `Tzip16Module` and add it as an extension to the `TezosToolkit`**
30
+
31
+ The constructor of the `Tzip16Module` takes an optional `MetadataProvider` as a parameter. When none is passed, the default `MetadataProvider` of octez.js is instantiated, and the default handlers (`HttpHandler`, `IpfsHandler`, and `TezosStorageHandler`) are used.
32
+ The `MetadataProvider` can be customized by the user if needed.
33
+
34
+ **Use the `tzip16` function to extend a contract abstraction**
35
+
36
+ ```js
37
+ import { TezosToolkit } from '@tezos-x/octez.js';
38
+ import { Tzip16Module, tzip16 } from '@tezos-x/octez.js-tzip16';
39
+
40
+ const Tezos = new TezosToolkit('https://YOUR_PREFERRED_RPC_URL');
41
+ Tezos.addExtension(new Tzip16Module());
42
+
43
+ const contract = await Tezos.contract.at("contractAddress", tzip16)
44
+ ```
45
+
46
+ ### Get the contract metadata
47
+
48
+ ```ts
49
+ const metadata = await contract.tzip16().getMetadata();
50
+ ```
51
+
52
+ The `getMetadata` method returns an object which contains the URI, the metadata in JSON format, an optional SHA256 hash of the metadata, and an optional integrity check result.
53
+
54
+ ### Execute off-chain views
55
+
56
+ ```ts
57
+ // Initialize off-chain views
58
+ const metadataViews = await contractAbstraction.tzip16().metadataViews();
59
+ const viewResult = await metadataViews.nameOfTheView().executeView(paramOfTheView);
60
+ ```
61
+
62
+ ## Additional info
63
+
64
+ See the top-level [https://github.com/trilitech/octez.js](https://github.com/trilitech/octez.js) file for details on reporting issues, contributing, and versioning.
65
+
66
+ ## Disclaimer
67
+
68
+ THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.tzip16 = tzip16;
4
+ const tzip16_contract_abstraction_1 = require("./tzip16-contract-abstraction");
5
+ const ABSTRACTION_KEY = Symbol('Tzip16ContractAbstractionObjectKey');
6
+ function tzip16(abs, context) {
7
+ return Object.assign(abs, {
8
+ // namespace tzip16
9
+ tzip16() {
10
+ if (!this[ABSTRACTION_KEY]) {
11
+ this[ABSTRACTION_KEY] = new tzip16_contract_abstraction_1.Tzip16ContractAbstraction(this, context);
12
+ }
13
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
14
+ return this[ABSTRACTION_KEY];
15
+ },
16
+ });
17
+ }
@@ -0,0 +1,138 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.NoParameterExpectedError = exports.ForbiddenInstructionInViewCodeError = exports.UnconfiguredContractMetadataProviderError = exports.InvalidContractMetadataTypeError = exports.ProtocolNotSupportedError = exports.InvalidContractMetadataError = exports.InvalidUriError = exports.UriNotFoundError = exports.ContractMetadataNotFoundError = exports.BigMapContractMetadataNotFoundError = exports.InvalidViewParameterError = void 0;
4
+ const octez_js_core_1 = require("@tezos-x/octez.js-core");
5
+ var octez_js_core_2 = require("@tezos-x/octez.js-core");
6
+ Object.defineProperty(exports, "InvalidViewParameterError", { enumerable: true, get: function () { return octez_js_core_2.InvalidViewParameterError; } });
7
+ /**
8
+ * @category Error
9
+ * @description Error that indicates missing big map metadata (non compliance to the TZIP-16 standard)
10
+ */
11
+ class BigMapContractMetadataNotFoundError extends octez_js_core_1.TaquitoError {
12
+ constructor(invalidBigMapId) {
13
+ super();
14
+ this.invalidBigMapId = invalidBigMapId;
15
+ this.name = 'BigMapContractMetadataNotFoundError';
16
+ this.message =
17
+ 'Non-compliance with the TZIP-016 standard. No big map named metadata was found in the contract storage.';
18
+ }
19
+ }
20
+ exports.BigMapContractMetadataNotFoundError = BigMapContractMetadataNotFoundError;
21
+ /**
22
+ * @category Error
23
+ * @description Error that indicates missing metadata in storage
24
+ */
25
+ class ContractMetadataNotFoundError extends octez_js_core_1.TaquitoError {
26
+ constructor(info) {
27
+ super();
28
+ this.info = info;
29
+ this.name = 'ContractMetadataNotFoundError';
30
+ this.message = `No metadata was found in the contract storage. ${info}`;
31
+ }
32
+ }
33
+ exports.ContractMetadataNotFoundError = ContractMetadataNotFoundError;
34
+ /**
35
+ * @category Error
36
+ * @description Error that indicates missing URI (non compliance to the TZIP-16 standard)
37
+ */
38
+ class UriNotFoundError extends octez_js_core_1.TaquitoError {
39
+ constructor() {
40
+ super();
41
+ this.name = 'UriNotFoundError';
42
+ this.message =
43
+ 'Non-compliance with the TZIP-016 standard. No URI found in the contract storage.';
44
+ }
45
+ }
46
+ exports.UriNotFoundError = UriNotFoundError;
47
+ /**
48
+ * @category Error
49
+ * @description Error that indicates an invalid URI (non compliance to the TZIP-16 standard)
50
+ */
51
+ class InvalidUriError extends octez_js_core_1.TaquitoError {
52
+ constructor(uri) {
53
+ super();
54
+ this.uri = uri;
55
+ this.name = 'InvalidUriError';
56
+ this.message = `Non-compliance with the TZIP-016 standard. The URI is invalid: ${uri}.`;
57
+ }
58
+ }
59
+ exports.InvalidUriError = InvalidUriError;
60
+ /**
61
+ * @category Error
62
+ * @description Error that indicates invalid metadata (non compliance to the TZIP-16 standard)
63
+ */
64
+ class InvalidContractMetadataError extends octez_js_core_1.TaquitoError {
65
+ constructor(invalidMetadata) {
66
+ super();
67
+ this.invalidMetadata = invalidMetadata;
68
+ this.name = 'InvalidContractMetadataError';
69
+ this.message = `The metadata found at the pointed ressource are not compliant with tzip16 standard: ${invalidMetadata}.`;
70
+ }
71
+ }
72
+ exports.InvalidContractMetadataError = InvalidContractMetadataError;
73
+ /**
74
+ * @category Error
75
+ * @description Error that indicates the uri protocol being passed or used is not supported
76
+ */
77
+ class ProtocolNotSupportedError extends octez_js_core_1.ParameterValidationError {
78
+ constructor(protocol) {
79
+ super();
80
+ this.protocol = protocol;
81
+ this.name = 'ProtocolNotSupportedError';
82
+ this.message = `The protocol found in the URI is not supported: ${protocol}.`;
83
+ }
84
+ }
85
+ exports.ProtocolNotSupportedError = ProtocolNotSupportedError;
86
+ /**
87
+ * @category Error
88
+ * @description Error that indicates the metadata type is invalid (non compliance to the TZIP-16 standard)
89
+ */
90
+ class InvalidContractMetadataTypeError extends octez_js_core_1.TaquitoError {
91
+ constructor() {
92
+ super();
93
+ this.name = 'InvalidContractMetadataTypeError';
94
+ this.message =
95
+ 'Non-compliance with the TZIP-016 standard. The type of metadata should be bytes.';
96
+ }
97
+ }
98
+ exports.InvalidContractMetadataTypeError = InvalidContractMetadataTypeError;
99
+ /**
100
+ * @category Error
101
+ * @description Error that indicates metadata provider being unconfigured in the TezosToolkit instance
102
+ */
103
+ class UnconfiguredContractMetadataProviderError extends octez_js_core_1.TezosToolkitConfigError {
104
+ constructor() {
105
+ super();
106
+ this.name = 'UnconfiguredContractMetadataProviderError';
107
+ this.message =
108
+ 'No metadata provider has been configured. The default one can be configured by calling addExtension(new Tzip16Module()) on your TezosToolkit instance.';
109
+ }
110
+ }
111
+ exports.UnconfiguredContractMetadataProviderError = UnconfiguredContractMetadataProviderError;
112
+ /**
113
+ * @category Error
114
+ * @description Error that indicates a forbidden instruction being found inside the View code
115
+ */
116
+ class ForbiddenInstructionInViewCodeError extends octez_js_core_1.TaquitoError {
117
+ constructor(instruction) {
118
+ super();
119
+ this.instruction = instruction;
120
+ this.name = 'ForbiddenInstructionInViewCodeError';
121
+ this.message = `Error found in the code of the view. It contains a forbidden instruction: ${instruction}.`;
122
+ }
123
+ }
124
+ exports.ForbiddenInstructionInViewCodeError = ForbiddenInstructionInViewCodeError;
125
+ /**
126
+ * @category Error
127
+ * @description Error that indicates parameters are being passed when it is not required
128
+ */
129
+ class NoParameterExpectedError extends octez_js_core_1.ParameterValidationError {
130
+ constructor(viewName, args) {
131
+ super();
132
+ this.viewName = viewName;
133
+ this.args = args;
134
+ this.name = 'NoParameterExpectedError';
135
+ this.message = `${viewName} Received ${args.length} arguments while expecting no parameter or 'Unit'`;
136
+ }
137
+ }
138
+ exports.NoParameterExpectedError = NoParameterExpectedError;
@@ -0,0 +1,31 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.HttpHandler = void 0;
13
+ const octez_js_http_utils_1 = require("@tezos-x/octez.js-http-utils");
14
+ class HttpHandler {
15
+ constructor() {
16
+ this.httpBackend = new octez_js_http_utils_1.HttpBackend();
17
+ }
18
+ getMetadata(_contractAbstraction_1, _a, _context_1) {
19
+ return __awaiter(this, arguments, void 0, function* (_contractAbstraction, { protocol, location }, _context) {
20
+ return this.httpBackend.createRequest({
21
+ url: `${protocol}:${decodeURIComponent(location)}`,
22
+ method: 'GET',
23
+ headers: {
24
+ 'Content-Type': 'text/plain; charset=utf-8'
25
+ },
26
+ json: false
27
+ });
28
+ });
29
+ }
30
+ }
31
+ exports.HttpHandler = HttpHandler;
@@ -0,0 +1,32 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.IpfsHttpHandler = void 0;
13
+ const octez_js_http_utils_1 = require("@tezos-x/octez.js-http-utils");
14
+ class IpfsHttpHandler {
15
+ constructor(ipfsGatheway) {
16
+ this.httpBackend = new octez_js_http_utils_1.HttpBackend();
17
+ this._ipfsGateway = ipfsGatheway ? ipfsGatheway : 'ipfs.io';
18
+ }
19
+ getMetadata(_contractAbstraction_1, _a, _context_1) {
20
+ return __awaiter(this, arguments, void 0, function* (_contractAbstraction, { location }, _context) {
21
+ return this.httpBackend.createRequest({
22
+ url: `https://${this._ipfsGateway}/ipfs/${location.substring(2)}/`,
23
+ method: 'GET',
24
+ headers: {
25
+ 'Content-Type': 'text/plain; charset=utf-8'
26
+ },
27
+ json: false
28
+ });
29
+ });
30
+ }
31
+ }
32
+ exports.IpfsHttpHandler = IpfsHttpHandler;
@@ -0,0 +1,62 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.TezosStorageHandler = void 0;
13
+ const octez_js_michelson_encoder_1 = require("@tezos-x/octez.js-michelson-encoder");
14
+ const octez_js_utils_1 = require("@tezos-x/octez.js-utils");
15
+ const errors_1 = require("../errors");
16
+ const typeOfValueToFind = {
17
+ prim: 'big_map',
18
+ args: [{ prim: 'string' }, { prim: 'bytes' }],
19
+ annots: ['%metadata'],
20
+ };
21
+ class TezosStorageHandler {
22
+ constructor() {
23
+ this.TEZOS_STORAGE_REGEX = /^(?:\/\/(KT1\w{33})(?:\.(.+))?\/)?([\w|%]+)$/;
24
+ }
25
+ getMetadata(contractAbstraction_1, _a, context_1) {
26
+ return __awaiter(this, arguments, void 0, function* (contractAbstraction, { location }, context) {
27
+ const parsedTezosStorageUri = this.parseTezosStorageUri(location);
28
+ if (!parsedTezosStorageUri) {
29
+ throw new errors_1.InvalidUriError(`tezos-storage:${location}`);
30
+ }
31
+ const script = yield context.readProvider.getScript(parsedTezosStorageUri.contractAddress || contractAbstraction.address, 'head');
32
+ const bigMapId = octez_js_michelson_encoder_1.Schema.fromRPCResponse({ script }).FindFirstInTopLevelPair(script.storage, typeOfValueToFind);
33
+ if (!bigMapId || !bigMapId.int) {
34
+ throw new errors_1.BigMapContractMetadataNotFoundError(bigMapId);
35
+ }
36
+ const bytes = yield context.contract.getBigMapKeyByID(bigMapId.int.toString(), parsedTezosStorageUri.path, new octez_js_michelson_encoder_1.Schema(typeOfValueToFind));
37
+ if (!bytes) {
38
+ throw new errors_1.ContractMetadataNotFoundError(`No '${parsedTezosStorageUri.path}' key found in the big map %metadata of the contract ${parsedTezosStorageUri.contractAddress || contractAbstraction.address}`);
39
+ }
40
+ if (!/^[0-9a-fA-F]*$/.test(bytes)) {
41
+ throw new errors_1.InvalidContractMetadataTypeError();
42
+ }
43
+ return (0, octez_js_utils_1.bytesToString)(bytes);
44
+ });
45
+ }
46
+ /**
47
+ * @description Extract the smart contract address, the network and the path pointing to the metadata from the uri
48
+ * @returns an object which contains the properties allowing to find where the metadata are located or it returns undefined if the uri is not valid
49
+ * @param tezosStorageURI URI (without the tezos-storage prefix)
50
+ */
51
+ parseTezosStorageUri(tezosStorageURI) {
52
+ const extractor = this.TEZOS_STORAGE_REGEX.exec(tezosStorageURI);
53
+ if (!extractor)
54
+ return;
55
+ return {
56
+ contractAddress: extractor[1],
57
+ network: extractor[2],
58
+ path: decodeURIComponent(extractor[3]),
59
+ };
60
+ }
61
+ }
62
+ exports.TezosStorageHandler = TezosStorageHandler;
@@ -0,0 +1,8 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ViewImplementationType = void 0;
4
+ var ViewImplementationType;
5
+ (function (ViewImplementationType) {
6
+ ViewImplementationType["MICHELSON_STORAGE"] = "michelsonStorageView";
7
+ ViewImplementationType["REST_API_QUERY"] = "restApiQuery";
8
+ })(ViewImplementationType || (exports.ViewImplementationType = ViewImplementationType = {}));
@@ -0,0 +1,68 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.MetadataProvider = void 0;
13
+ const errors_1 = require("./errors");
14
+ const tzip16_utils_1 = require("./tzip16-utils");
15
+ /**
16
+ * @description: Metadata Provider
17
+ */
18
+ class MetadataProvider {
19
+ constructor(handlers) {
20
+ this.handlers = handlers;
21
+ this.PROTOCOL_REGEX = /(?:sha256:\/\/0x(.*)\/)?(https?|ipfs|tezos-storage):(.*)/;
22
+ }
23
+ /**
24
+ * @description Fetch the metadata by using the appropriate handler based on the protcol found in the URI
25
+ * @returns an object which contains the uri, the metadata, an optional integrity check result and an optional SHA256 hash
26
+ * @param _contractAbstraction the contract abstraction which contains the URI in its storage
27
+ * @param _uri the decoded uri found in the storage
28
+ * @param context the TezosToolkit Context
29
+ */
30
+ provideMetadata(contractAbstraction, uri, context) {
31
+ return __awaiter(this, void 0, void 0, function* () {
32
+ const uriInfo = this.extractProtocolInfo(uri);
33
+ if (!uriInfo || !uriInfo.location) {
34
+ throw new errors_1.InvalidUriError(uri);
35
+ }
36
+ const handler = this.handlers.get(uriInfo.protocol);
37
+ if (!handler) {
38
+ throw new errors_1.ProtocolNotSupportedError(uriInfo.protocol);
39
+ }
40
+ const metadata = yield handler.getMetadata(contractAbstraction, uriInfo, context);
41
+ const sha256Hash = (0, tzip16_utils_1.calculateSHA256Hash)(metadata);
42
+ let metadataJSON;
43
+ try {
44
+ metadataJSON = JSON.parse(metadata);
45
+ }
46
+ catch (ex) {
47
+ throw new errors_1.InvalidContractMetadataError(metadata);
48
+ }
49
+ return {
50
+ uri,
51
+ metadata: metadataJSON,
52
+ integrityCheckResult: uriInfo.sha256hash ? uriInfo.sha256hash === sha256Hash : undefined,
53
+ sha256Hash: uriInfo.sha256hash ? sha256Hash : undefined,
54
+ };
55
+ });
56
+ }
57
+ extractProtocolInfo(_uri) {
58
+ const extractor = this.PROTOCOL_REGEX.exec(_uri);
59
+ if (!extractor)
60
+ return;
61
+ return {
62
+ sha256hash: extractor[1],
63
+ protocol: extractor[2],
64
+ location: extractor[3],
65
+ };
66
+ }
67
+ }
68
+ exports.MetadataProvider = MetadataProvider;
@@ -0,0 +1,36 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ exports.VERSION = void 0;
18
+ /**
19
+ * @packageDocumentation
20
+ * @module @tezos-x/octez.js-tzip16
21
+ */
22
+ __exportStar(require("./handlers/http-handler"), exports);
23
+ __exportStar(require("./handlers/tezos-storage-handler"), exports);
24
+ __exportStar(require("./handlers/ipfs-handler"), exports);
25
+ __exportStar(require("./composer"), exports);
26
+ __exportStar(require("./metadata-interface"), exports);
27
+ __exportStar(require("./metadata-provider"), exports);
28
+ __exportStar(require("./tzip16-contract-abstraction"), exports);
29
+ __exportStar(require("./errors"), exports);
30
+ __exportStar(require("./tzip16-extension"), exports);
31
+ __exportStar(require("./tzip16-utils"), exports);
32
+ __exportStar(require("./viewKind/interface"), exports);
33
+ __exportStar(require("./viewKind/michelson-storage-view"), exports);
34
+ __exportStar(require("./viewKind/viewFactory"), exports);
35
+ var version_1 = require("./version");
36
+ Object.defineProperty(exports, "VERSION", { enumerable: true, get: function () { return version_1.VERSION; } });
@@ -0,0 +1,174 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.Tzip16ContractAbstraction = void 0;
13
+ const octez_js_1 = require("@tezos-x/octez.js");
14
+ const octez_js_utils_1 = require("@tezos-x/octez.js-utils");
15
+ const errors_1 = require("./errors");
16
+ const bignumber_js_1 = require("bignumber.js");
17
+ const octez_js_michelson_encoder_1 = require("@tezos-x/octez.js-michelson-encoder");
18
+ const viewFactory_1 = require("./viewKind/viewFactory");
19
+ const metadataBigMapType = {
20
+ prim: 'big_map',
21
+ args: [{ prim: 'string' }, { prim: 'bytes' }],
22
+ annots: ['%metadata'],
23
+ };
24
+ class Tzip16ContractAbstraction {
25
+ constructor(constractAbstraction, context) {
26
+ this.constractAbstraction = constractAbstraction;
27
+ this.context = context;
28
+ this._viewFactory = new viewFactory_1.ViewFactory();
29
+ this._metadataViewsObject = {};
30
+ this._metadataProvider = context.metadataProvider;
31
+ }
32
+ findMetadataBigMap() {
33
+ return __awaiter(this, void 0, void 0, function* () {
34
+ const metadataBigMapId = this.constractAbstraction.schema.FindFirstInTopLevelPair(yield this.context.readProvider.getStorage(this.constractAbstraction.address, 'head'), metadataBigMapType);
35
+ if (!metadataBigMapId || !metadataBigMapId.int) {
36
+ throw new errors_1.BigMapContractMetadataNotFoundError(metadataBigMapId);
37
+ }
38
+ return new octez_js_1.BigMapAbstraction(new bignumber_js_1.default(metadataBigMapId['int']), new octez_js_michelson_encoder_1.Schema(metadataBigMapType), this.context.contract);
39
+ });
40
+ }
41
+ getUriOrFail() {
42
+ return __awaiter(this, void 0, void 0, function* () {
43
+ const metadataBigMap = yield this.findMetadataBigMap();
44
+ const uri = yield metadataBigMap.get('');
45
+ if (!uri) {
46
+ throw new errors_1.UriNotFoundError();
47
+ }
48
+ return uri;
49
+ });
50
+ }
51
+ /**
52
+ * @description Return an object containing the metadata, the uri, an optional integrity check result and an optional sha256 hash
53
+ */
54
+ getMetadata() {
55
+ return __awaiter(this, void 0, void 0, function* () {
56
+ if (!this._metadataProvider) {
57
+ throw new errors_1.UnconfiguredContractMetadataProviderError();
58
+ }
59
+ if (!this._metadataEnvelope) {
60
+ const uri = yield this.getUriOrFail();
61
+ this._metadataEnvelope = yield this._metadataProvider.provideMetadata(this.constractAbstraction, (0, octez_js_utils_1.bytesToString)(uri), this.context);
62
+ }
63
+ return this._metadataEnvelope;
64
+ });
65
+ }
66
+ metadataName() {
67
+ return __awaiter(this, void 0, void 0, function* () {
68
+ if (!this._metadataEnvelope) {
69
+ yield this.getMetadata();
70
+ }
71
+ return this._metadataEnvelope.metadata.name;
72
+ });
73
+ }
74
+ metadataDescription() {
75
+ return __awaiter(this, void 0, void 0, function* () {
76
+ if (!this._metadataEnvelope)
77
+ yield this.getMetadata();
78
+ return this._metadataEnvelope.metadata.description;
79
+ });
80
+ }
81
+ metadataVersion() {
82
+ return __awaiter(this, void 0, void 0, function* () {
83
+ if (!this._metadataEnvelope)
84
+ yield this.getMetadata();
85
+ return this._metadataEnvelope.metadata.version;
86
+ });
87
+ }
88
+ metadataLicense() {
89
+ return __awaiter(this, void 0, void 0, function* () {
90
+ if (!this._metadataEnvelope)
91
+ yield this.getMetadata();
92
+ return this._metadataEnvelope.metadata.license;
93
+ });
94
+ }
95
+ metadataAuthors() {
96
+ return __awaiter(this, void 0, void 0, function* () {
97
+ if (!this._metadataEnvelope)
98
+ yield this.getMetadata();
99
+ return this._metadataEnvelope.metadata.authors;
100
+ });
101
+ }
102
+ metadataHomepage() {
103
+ return __awaiter(this, void 0, void 0, function* () {
104
+ if (!this._metadataEnvelope)
105
+ yield this.getMetadata();
106
+ return this._metadataEnvelope.metadata.homepage;
107
+ });
108
+ }
109
+ metadataSource() {
110
+ return __awaiter(this, void 0, void 0, function* () {
111
+ if (!this._metadataEnvelope)
112
+ yield this.getMetadata();
113
+ return this._metadataEnvelope.metadata.source;
114
+ });
115
+ }
116
+ metadataInterfaces() {
117
+ return __awaiter(this, void 0, void 0, function* () {
118
+ if (!this._metadataEnvelope)
119
+ yield this.getMetadata();
120
+ return this._metadataEnvelope.metadata.interfaces;
121
+ });
122
+ }
123
+ metadataErrors() {
124
+ return __awaiter(this, void 0, void 0, function* () {
125
+ if (!this._metadataEnvelope)
126
+ yield this.getMetadata();
127
+ return this._metadataEnvelope.metadata.errors;
128
+ });
129
+ }
130
+ metadataViews() {
131
+ return __awaiter(this, void 0, void 0, function* () {
132
+ if (Object.keys(this._metadataViewsObject).length === 0) {
133
+ yield this.initializeMetadataViewsList();
134
+ }
135
+ return this._metadataViewsObject;
136
+ });
137
+ }
138
+ initializeMetadataViewsList() {
139
+ return __awaiter(this, void 0, void 0, function* () {
140
+ var _a;
141
+ const { metadata } = yield this.getMetadata();
142
+ const metadataViews = {};
143
+ (_a = metadata.views) === null || _a === void 0 ? void 0 : _a.forEach((view) => this.createViewImplementations(view, metadataViews));
144
+ this._metadataViewsObject = metadataViews;
145
+ });
146
+ }
147
+ generateIndexedViewName(viewName, metadataViews) {
148
+ let i = 1;
149
+ if (viewName in metadataViews) {
150
+ while (`${viewName}${i}` in metadataViews) {
151
+ i++;
152
+ }
153
+ viewName = `${viewName}${i}`;
154
+ }
155
+ return viewName;
156
+ }
157
+ createViewImplementations(view, metadataViews) {
158
+ var _a;
159
+ for (const viewImplementation of (_a = view === null || view === void 0 ? void 0 : view.implementations) !== null && _a !== void 0 ? _a : []) {
160
+ if (view.name) {
161
+ // when views have the same name, add an index at the end of the name
162
+ const viewName = this.generateIndexedViewName(view.name, metadataViews);
163
+ const metadataView = this._viewFactory.getView(viewName, this.context.rpc, this.context.readProvider, this.constractAbstraction, viewImplementation);
164
+ if (metadataView) {
165
+ metadataViews[viewName] = metadataView;
166
+ }
167
+ else {
168
+ console.warn(`Skipped generating ${viewName} because the view has an unsupported type: ${this._viewFactory.getImplementationType(viewImplementation)}`);
169
+ }
170
+ }
171
+ }
172
+ }
173
+ }
174
+ exports.Tzip16ContractAbstraction = Tzip16ContractAbstraction;
@@ -0,0 +1,22 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Tzip16Module = exports.DEFAULT_HANDLERS = void 0;
4
+ const metadata_provider_1 = require("./metadata-provider");
5
+ const http_handler_1 = require("./handlers/http-handler");
6
+ const tezos_storage_handler_1 = require("./handlers/tezos-storage-handler");
7
+ const ipfs_handler_1 = require("./handlers/ipfs-handler");
8
+ exports.DEFAULT_HANDLERS = new Map([
9
+ ['http', new http_handler_1.HttpHandler()],
10
+ ['https', new http_handler_1.HttpHandler()],
11
+ ['tezos-storage', new tezos_storage_handler_1.TezosStorageHandler()],
12
+ ['ipfs', new ipfs_handler_1.IpfsHttpHandler()]
13
+ ]);
14
+ class Tzip16Module {
15
+ constructor(metadataProvider) {
16
+ this._metadataProvider = metadataProvider ? metadataProvider : new metadata_provider_1.MetadataProvider(exports.DEFAULT_HANDLERS);
17
+ }
18
+ configureContext(context) {
19
+ Object.assign(context, { metadataProvider: this._metadataProvider });
20
+ }
21
+ }
22
+ exports.Tzip16Module = Tzip16Module;