@taquito/taquito
Version:
High level functionality that builds upon the other packages in the Tezos Typescript Library Suite.
170 lines (169 loc) • 10 kB
JavaScript
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.ContractAbstraction = exports.ContractView = exports.DEFAULT_SMART_CONTRACT_METHOD_NAME = void 0;
const michelson_encoder_1 = require("@taquito/michelson-encoder");
const utils_1 = require("@taquito/utils");
const contract_method_factory_1 = require("./contract-methods/contract-method-factory");
const errors_1 = require("./errors");
const core_1 = require("@taquito/core");
const constants_1 = require("./constants");
Object.defineProperty(exports, "DEFAULT_SMART_CONTRACT_METHOD_NAME", { enumerable: true, get: function () { return constants_1.DEFAULT_SMART_CONTRACT_METHOD_NAME; } });
/**
* @description Utility class to retrieve data from a smart contract's storage without incurring fees via a contract's view method
*/
class ContractView {
constructor(currentContract, name, callbackParametersSchema, parameterSchema, args, rpc, readProvider) {
this.currentContract = currentContract;
this.name = name;
this.callbackParametersSchema = callbackParametersSchema;
this.parameterSchema = parameterSchema;
this.args = args;
this.rpc = rpc;
this.readProvider = readProvider;
}
read(chainId) {
return __awaiter(this, void 0, void 0, function* () {
const chainIdValidation = (0, utils_1.validateChain)(chainId !== null && chainId !== void 0 ? chainId : '');
if ((0, utils_1.validateContractAddress)(chainId !== null && chainId !== void 0 ? chainId : '') == utils_1.ValidationResult.VALID) {
throw new core_1.DeprecationError(`Since version 12, the lambda view no longer depends on a lambda contract. The read method no longer accepts a contract address as a parameter.`);
}
else if (chainId && chainIdValidation !== utils_1.ValidationResult.VALID) {
throw new core_1.InvalidChainIdError(chainId, chainIdValidation);
}
const arg = this.parameterSchema.Encode(...this.args);
const result = yield this.rpc.runView({
contract: this.currentContract.address,
entrypoint: this.name,
input: arg,
chain_id: chainId ? chainId : yield this.readProvider.getChainId(),
});
return this.callbackParametersSchema.Execute(result.data);
});
}
}
exports.ContractView = ContractView;
const validateArgs = (args, schema, name) => {
const sigs = schema.ExtractSignatures();
if (!sigs.find((x) => x.length === args.length)) {
throw new errors_1.InvalidParameterError(name, sigs, args);
}
};
// lambda view tzip4
const isView = (entrypoint) => {
let isView = false;
if ('prim' in entrypoint && entrypoint.prim === 'pair' && entrypoint.args) {
const lastElement = entrypoint.args[entrypoint.args.length - 1];
if ('prim' in lastElement && lastElement.prim === 'contract') {
isView = true;
}
}
return isView;
};
/**
* @description Smart contract abstraction
*/
class ContractAbstraction {
constructor(address, script, provider, storageProvider, entrypoints, rpc, readProvider) {
this.address = address;
this.script = script;
this.storageProvider = storageProvider;
this.entrypoints = entrypoints;
this.rpc = rpc;
this.readProvider = readProvider;
/**
* @description Contains methods that are implemented by the target Tezos Smart Contract, and offers the user to call the Smart Contract methods as if they were native TS/JS methods.
* `methodsObject` serves the exact same purpose as the `methods` member. The difference is that it allows passing the parameter in an object format when calling the smart contract method (instead of the flattened representation)
* NB: if the contract contains annotation it will include named properties; if not it will be indexed by a number.
*
*/
this.methodsObject = {};
/**
* @description Contains lamda views (tzip4) that are implemented by the target Tezos Smart Contract, and offers the user to call the lambda views as if they were native TS/JS methods.
* NB: These are the view defined in the tzip4 standard, not the views introduced by the Hangzhou protocol.
*/
this.views = {};
/**
* @description Contains on-chain views that are defined by the target Tezos Smart Contract, and offers the user to simulate the views execution as if they were native TS/JS methods.
* NB: the expected format for the parameter when calling a smart contract view is the object format (same format as for the storage) and not the flattened representation.
*
*/
this.contractViews = {};
this.contractMethodFactory = new contract_method_factory_1.ContractMethodFactory(provider, address);
this.schema = michelson_encoder_1.Schema.fromRPCResponse({ script: this.script });
this.parameterSchema = michelson_encoder_1.ParameterSchema.fromRPCResponse({ script: this.script });
this.viewSchema = michelson_encoder_1.ViewSchema.fromRPCResponse({ script: this.script });
if (this.viewSchema.length !== 0) {
this._initializeOnChainViews(this, rpc, this.readProvider, this.viewSchema);
}
this.eventSchema = michelson_encoder_1.EventSchema.fromRPCResponse({ script: this.script });
this._initializeMethods(this, this.entrypoints.entrypoints, this.rpc, this.readProvider);
}
_initializeMethods(currentContract, entrypoints, rpc, readProvider) {
const parameterSchema = this.parameterSchema;
const keys = Object.keys(entrypoints);
if (parameterSchema.isMultipleEntryPoint) {
keys.forEach((smartContractMethodName) => {
const smartContractMethodSchema = new michelson_encoder_1.ParameterSchema(entrypoints[smartContractMethodName]);
this.methodsObject[smartContractMethodName] = function (args) {
return currentContract.contractMethodFactory.createContractMethodObjectParam(smartContractMethodSchema, smartContractMethodName, args);
};
if (isView(entrypoints[smartContractMethodName])) {
const view = function (...args) {
const entrypointParamWithoutCallback = entrypoints[smartContractMethodName]
.args[0];
const smartContractMethodSchemaWithoutCallback = new michelson_encoder_1.ParameterSchema(entrypointParamWithoutCallback);
const parametersCallback = entrypoints[smartContractMethodName].args[1]
.args[0];
const smartContractMethodCallbackSchema = new michelson_encoder_1.ParameterSchema(parametersCallback);
validateArgs(args, smartContractMethodSchemaWithoutCallback, smartContractMethodName);
return new ContractView(currentContract, smartContractMethodName, smartContractMethodCallbackSchema, smartContractMethodSchemaWithoutCallback, args, rpc, readProvider);
};
this.views[smartContractMethodName] = view;
}
});
// Deal with methods with no annotations which were not discovered by the RPC endpoint
// Methods with no annotations are discovered using parameter schema
const generatedSchema = parameterSchema.generateSchema();
const schemaKeys = generatedSchema.schema && typeof generatedSchema.schema === 'object'
? Object.keys(generatedSchema.schema)
: [];
const anonymousMethods = schemaKeys.filter((key) => Object.keys(entrypoints).indexOf(key) === -1);
anonymousMethods.forEach((smartContractMethodName) => {
this.methodsObject[smartContractMethodName] = function (args) {
return currentContract.contractMethodFactory.createContractMethodObjectParam(parameterSchema, smartContractMethodName, args, false, true);
};
});
}
else {
const smartContractMethodSchema = this.parameterSchema;
this.methodsObject[constants_1.DEFAULT_SMART_CONTRACT_METHOD_NAME] =
function (args) {
return currentContract.contractMethodFactory.createContractMethodObjectParam(smartContractMethodSchema, constants_1.DEFAULT_SMART_CONTRACT_METHOD_NAME, args, false);
};
}
}
_initializeOnChainViews(currentContract, rpc, readProvider, allContractViews) {
const storageType = this.schema.val;
allContractViews.forEach((viewSchema) => {
this.contractViews[viewSchema.viewName] = function (args) {
return currentContract.contractMethodFactory.createContractViewObjectParam(rpc, readProvider, viewSchema, storageType, args);
};
});
}
/**
* @description Return a friendly representation of the smart contract storage
*/
storage() {
return this.storageProvider.getStorage(this.address, this.schema);
}
}
exports.ContractAbstraction = ContractAbstraction;