UNPKG

@aeternity/aepp-sdk

Version:
528 lines (449 loc) 19.9 kB
import _Object$keys from "@babel/runtime-corejs3/core-js-stable/object/keys"; import _Object$getOwnPropertySymbols from "@babel/runtime-corejs3/core-js-stable/object/get-own-property-symbols"; import _filterInstanceProperty from "@babel/runtime-corejs3/core-js-stable/instance/filter"; import _Object$getOwnPropertyDescriptor from "@babel/runtime-corejs3/core-js-stable/object/get-own-property-descriptor"; import _forEachInstanceProperty from "@babel/runtime-corejs3/core-js-stable/instance/for-each"; import _Object$getOwnPropertyDescriptors from "@babel/runtime-corejs3/core-js-stable/object/get-own-property-descriptors"; import _Object$defineProperties from "@babel/runtime-corejs3/core-js-stable/object/define-properties"; import _Object$defineProperty from "@babel/runtime-corejs3/core-js-stable/object/define-property"; import _merge from "ramda/src/merge"; import _path from "ramda/src/path"; import _prop from "ramda/src/prop"; import _defaultTo from "ramda/src/defaultTo"; import _defineProperty from "@babel/runtime-corejs3/helpers/defineProperty"; import _asyncToGenerator from "@babel/runtime-corejs3/helpers/asyncToGenerator"; import _regeneratorRuntime from "@babel/runtime-corejs3/regenerator"; import _concatInstanceProperty from "@babel/runtime-corejs3/core-js-stable/instance/concat"; import _mapInstanceProperty from "@babel/runtime-corejs3/core-js-stable/instance/map"; function ownKeys(object, enumerableOnly) { var keys = _Object$keys(object); if (_Object$getOwnPropertySymbols) { var symbols = _Object$getOwnPropertySymbols(object); if (enumerableOnly) symbols = _filterInstanceProperty(symbols).call(symbols, function (sym) { return _Object$getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; } function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { var _context7; _forEachInstanceProperty(_context7 = ownKeys(Object(source), true)).call(_context7, function (key) { _defineProperty(target, key, source[key]); }); } else if (_Object$getOwnPropertyDescriptors) { _Object$defineProperties(target, _Object$getOwnPropertyDescriptors(source)); } else { var _context8; _forEachInstanceProperty(_context8 = ownKeys(Object(source))).call(_context8, function (key) { _Object$defineProperty(target, key, _Object$getOwnPropertyDescriptor(source, key)); }); } } return target; } import BigNumber from 'bignumber.js'; import { buildContractMethods, decodeCallResult, decodeEvents, getFunctionACI, prepareArgsForEncode as prepareArgs } from './helpers'; import { isAddressValid } from '../../utils/crypto'; /** * Generate contract ACI object with predefined js methods for contract usage - can be used for creating a reference to already deployed contracts * @alias module:@aeternity/aepp-sdk/es/contract/aci * @param {String} source Contract source code * @param {Object} [options={}] Options object * @param {String} [options.aci] Contract ACI * @param {String} [options.contractAddress] Contract address * @param {Object} [options.filesystem] Contact source external namespaces map * @param {Object} [options.forceCodeCheck=true] Don't check contract code * @param {Object} [options.opt] Contract options * @return {ContractInstance} JS Contract API * @example * const contractIns = await client.getContractInstance(sourceCode) * await contractIns.deploy([321]) or await contractIns.methods.init(321) * const callResult = await contractIns.call('setState', [123]) or await contractIns.methods.setState.send(123, options) * const staticCallResult = await contractIns.call('setState', [123], { callStatic: true }) or await contractIns.methods.setState.get(123, options) * Also you can call contract like: await contractIns.methods.setState(123, options) * Then sdk decide to make on-chain or static call(dry-run API) transaction based on function is stateful or not */ export default function getContractInstance(_x) { return _getContractInstance.apply(this, arguments); } function _getContractInstance() { _getContractInstance = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee4(source) { var _context5; var _ref, aci, contractAddress, _ref$filesystem, filesystem, _ref$forceCodeCheck, forceCodeCheck, opt, defaultOptions, instance, contract, onChanByteCode, isCorrespondingBytecode, _args4 = arguments; return _regeneratorRuntime.wrap(function _callee4$(_context6) { while (1) { switch (_context6.prev = _context6.next) { case 0: _ref = _args4.length > 1 && _args4[1] !== undefined ? _args4[1] : {}, aci = _ref.aci, contractAddress = _ref.contractAddress, _ref$filesystem = _ref.filesystem, filesystem = _ref$filesystem === void 0 ? {} : _ref$filesystem, _ref$forceCodeCheck = _ref.forceCodeCheck, forceCodeCheck = _ref$forceCodeCheck === void 0 ? true : _ref$forceCodeCheck, opt = _ref.opt; _context6.t0 = aci; if (_context6.t0) { _context6.next = 6; break; } _context6.next = 5; return this.contractGetACI(source, { filesystem: filesystem }); case 5: _context6.t0 = _context6.sent; case 6: aci = _context6.t0; if (!contractAddress) { _context6.next = 11; break; } _context6.next = 10; return this.resolveName(contractAddress, 'ct', { resolveByNode: true }); case 10: contractAddress = _context6.sent; case 11: defaultOptions = _objectSpread(_objectSpread({}, this.Ae.defaults), {}, { skipArgsConvert: false, skipTransformDecoded: false, callStatic: false, waitMined: true, verify: false, filesystem: filesystem }); instance = { "interface": _defaultTo(null, _prop('interface', aci)), aci: _defaultTo(null, _path(['encoded_aci', 'contract'], aci)), externalAci: aci.external_encoded_aci ? _mapInstanceProperty(_context5 = aci.external_encoded_aci).call(_context5, function (a) { return a.contract || a.namespace; }) : [], source: source, compiled: null, deployInfo: { address: contractAddress }, options: _merge(defaultOptions, opt), compilerVersion: this.compilerVersion, setOptions: function setOptions(opt) { this.options = _merge(this.options, opt); } }; // Check for valid contract address and contract code if (!contractAddress) { _context6.next = 30; break; } if (isAddressValid(contractAddress, 'ct')) { _context6.next = 16; break; } throw new Error('Invalid contract address'); case 16: _context6.next = 18; return this.getContract(contractAddress)["catch"](function (e) { return null; }); case 18: contract = _context6.sent; if (!(!contract || !contract.active)) { _context6.next = 21; break; } throw new Error("Contract with address ".concat(contractAddress, " not found on-chain or not active")); case 21: if (forceCodeCheck) { _context6.next = 30; break; } _context6.next = 24; return this.getContractByteCode(contractAddress); case 24: onChanByteCode = _context6.sent.bytecode; _context6.next = 27; return this.validateByteCodeAPI(onChanByteCode, instance.source, instance.options)["catch"](function (e) { return false; }); case 27: isCorrespondingBytecode = _context6.sent; if (isCorrespondingBytecode) { _context6.next = 30; break; } throw new Error('Contract source do not correspond to the contract bytecode deployed on the chain'); case 30: /** * Compile contract * @alias module:@aeternity/aepp-sdk/es/contract/aci * @rtype () => ContractInstance: Object * @return {ContractInstance} Contract ACI object with predefined js methods for contract usage */ instance.compile = compile({ client: this, instance: instance }); /** * Deploy contract * @alias module:@aeternity/aepp-sdk/es/contract/aci * @rtype (init: Array, options: Object = { skipArgsConvert: false }) => ContractInstance: Object * @param {Array} init Contract init function arguments array * @param {Object} [options={}] options Options object * @param {Boolean} [options.skipArgsConvert=false] Skip Validation and Transforming arguments before prepare call-data * @return {ContractInstance} Contract ACI object with predefined js methods for contract usage */ instance.deploy = deploy({ client: this, instance: instance }); /** * Call contract function * @alias module:@aeternity/aepp-sdk/es/contract/aci * @rtype (init: Array, options: Object = { skipArgsConvert: false, skipTransformDecoded: false, callStatic: false }) => CallResult: Object * @param {String} fn Function name * @param {Array} params Array of function arguments * @param {Object} [options={}] Array of function arguments * @param {Boolean} [options.skipArgsConvert=false] Skip Validation and Transforming arguments before prepare call-data * @param {Boolean} [options.skipTransformDecoded=false] Skip Transform decoded data to JS type * @param {Boolean} [options.callStatic=false] Static function call * @return {Object} CallResult */ instance.call = call({ client: this, instance: instance }); /** * Decode Events * @alias module:@aeternity/aepp-sdk/es/contract/aci * @rtype (fn: String, events: Array) => DecodedEvents: Array * @param {String} fn Function name * @param {Array} events Array of encoded events(callRes.result.log) * @return {Object} DecodedEvents */ instance.decodeEvents = eventDecode({ instance: instance }); /** * Generate proto function based on contract function using Contract ACI schema * All function can be called like: * 'await contract.methods.testFunction()' -> then sdk will decide to use dry-run or send tx on-chain base on if function stateful or not. * Also you can manually do that: * `await contract.methods.testFunction.get()` -> use call-static(dry-run) * `await contract.methods.testFunction.send()` -> send tx on-chain */ instance.methods = buildContractMethods(instance)(); return _context6.abrupt("return", instance); case 36: case "end": return _context6.stop(); } } }, _callee4, this); })); return _getContractInstance.apply(this, arguments); } var eventDecode = function eventDecode(_ref2) { var instance = _ref2.instance; return function (fn, events) { return decodeEvents(events, getFunctionACI(instance.aci, fn, { external: instance.externalAci })); }; }; var call = function call(_ref3) { var client = _ref3.client, instance = _ref3.instance; return /*#__PURE__*/function () { var _ref4 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee(fn) { var _context; var params, options, opt, fnACI, source, result, _args = arguments; return _regeneratorRuntime.wrap(function _callee$(_context2) { while (1) { switch (_context2.prev = _context2.next) { case 0: params = _args.length > 1 && _args[1] !== undefined ? _args[1] : []; options = _args.length > 2 && _args[2] !== undefined ? _args[2] : {}; opt = _objectSpread(_objectSpread({}, instance.options), options); fnACI = getFunctionACI(instance.aci, fn, { external: instance.externalAci }); source = opt.source || instance.source; if (fn) { _context2.next = 7; break; } throw new Error('Function name is required'); case 7: if (instance.deployInfo.address) { _context2.next = 9; break; } throw new Error('You need to deploy contract before calling!'); case 9: if (!(BigNumber(opt.amount).gt(0) && Object.prototype.hasOwnProperty.call(fnACI, 'payable') && !fnACI.payable)) { _context2.next = 11; break; } throw new Error(_concatInstanceProperty(_context = "You try to pay \"".concat(opt.amount, "\" to function \"")).call(_context, fn, "\" which is not payable. Only payable function can accept tokens")); case 11: if (opt.skipArgsConvert) { _context2.next = 17; break; } _context2.next = 14; return prepareArgs(fnACI, params); case 14: _context2.t0 = _context2.sent; _context2.next = 18; break; case 17: _context2.t0 = params; case 18: params = _context2.t0; if (!opt.callStatic) { _context2.next = 25; break; } _context2.next = 22; return client.contractCallStatic(source, instance.deployInfo.address, fn, params, opt); case 22: _context2.t1 = _context2.sent; _context2.next = 28; break; case 25: _context2.next = 27; return client.contractCall(source, instance.deployInfo.address, fn, params, opt); case 27: _context2.t1 = _context2.sent; case 28: result = _context2.t1; _context2.t2 = _objectSpread; _context2.t3 = _objectSpread({}, result); if (!opt.waitMined) { _context2.next = 37; break; } _context2.next = 34; return decodeCallResult(result, fnACI, opt); case 34: _context2.t4 = _context2.sent; _context2.next = 38; break; case 37: _context2.t4 = {}; case 38: _context2.t5 = _context2.t4; return _context2.abrupt("return", (0, _context2.t2)(_context2.t3, _context2.t5)); case 40: case "end": return _context2.stop(); } } }, _callee); })); return function (_x2) { return _ref4.apply(this, arguments); }; }(); }; var deploy = function deploy(_ref5) { var client = _ref5.client, instance = _ref5.instance; return /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee2() { var init, options, opt, fnACI, source, _yield$client$contrac, owner, transaction, address, createdAt, result, rawTx, _args2 = arguments; return _regeneratorRuntime.wrap(function _callee2$(_context3) { while (1) { switch (_context3.prev = _context3.next) { case 0: init = _args2.length > 0 && _args2[0] !== undefined ? _args2[0] : []; options = _args2.length > 1 && _args2[1] !== undefined ? _args2[1] : {}; opt = _objectSpread(_objectSpread({}, instance.options), options); fnACI = getFunctionACI(instance.aci, 'init', { external: instance.externalAci }); source = opt.source || instance.source; if (instance.compiled) { _context3.next = 8; break; } _context3.next = 8; return instance.compile(opt); case 8: if (opt.skipArgsConvert) { _context3.next = 14; break; } _context3.next = 11; return prepareArgs(fnACI, init); case 11: _context3.t0 = _context3.sent; _context3.next = 15; break; case 14: _context3.t0 = init; case 15: init = _context3.t0; if (!opt.callStatic) { _context3.next = 20; break; } return _context3.abrupt("return", client.contractCallStatic(source, null, 'init', init, _objectSpread(_objectSpread({}, opt), {}, { bytecode: instance.compiled }))); case 20: _context3.next = 22; return client.contractDeploy(instance.compiled, opt.source || instance.source, init, opt); case 22: _yield$client$contrac = _context3.sent; owner = _yield$client$contrac.owner; transaction = _yield$client$contrac.transaction; address = _yield$client$contrac.address; createdAt = _yield$client$contrac.createdAt; result = _yield$client$contrac.result; rawTx = _yield$client$contrac.rawTx; instance.deployInfo = { owner: owner, transaction: transaction, address: address, createdAt: createdAt, result: result, rawTx: rawTx }; return _context3.abrupt("return", instance.deployInfo); case 31: case "end": return _context3.stop(); } } }, _callee2); })); }; var compile = function compile(_ref7) { var client = _ref7.client, instance = _ref7.instance; return /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee3() { var options, _yield$client$contrac2, bytecode, _args3 = arguments; return _regeneratorRuntime.wrap(function _callee3$(_context4) { while (1) { switch (_context4.prev = _context4.next) { case 0: options = _args3.length > 0 && _args3[0] !== undefined ? _args3[0] : {}; _context4.next = 3; return client.contractCompile(instance.source, _objectSpread(_objectSpread({}, instance.options), options)); case 3: _yield$client$contrac2 = _context4.sent; bytecode = _yield$client$contrac2.bytecode; instance.compiled = bytecode; return _context4.abrupt("return", instance.compiled); case 7: case "end": return _context4.stop(); } } }, _callee3); })); }; //# sourceMappingURL=index.js.map