laksa-core-contract
Version:
Contract instance for laksa
1,611 lines (1,420 loc) • 51.5 kB
JavaScript
/**
* This source code is being disclosed to you solely for the purpose of your participation in
* testing Zilliqa and Laksa. You may view, compile and run the code for that purpose and pursuant to
* the protocols and algorithms that are programmed into, and intended by, the code. You may
* not do anything else with the code without express permission from Zilliqa Research Pte. Ltd.,
* including modifying or publishing the code (or any part of it), and developing or forming
* another public or private blockchain network. This source code is provided ‘as is’ and no
* warranties are given as to title or non-infringement, merchantability or fitness for purpose
* and, to the extent permitted by law, all liability for your use of the code is disclaimed.
* Some programs in this code are governed by the GNU General Public License v3.0 (available at
* https://www.gnu.org/licenses/gpl-3.0.en.html) (‘GPLv3’). The programs that are governed by
* GPLv3.0 are those programs that are located in the folders src/depends and tests/depends
* and which include a reference to GPLv3 in their program files.
*/
'use strict';
Object.defineProperty(exports, '__esModule', { value: true });
function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; }
require('core-js/modules/es6.array.find');
require('core-js/modules/es6.regexp.match');
require('core-js/modules/es6.number.constructor');
var laksaUtils = require('laksa-utils');
require('core-js/modules/es6.function.name');
var _classCallCheck = _interopDefault(require('@babel/runtime/helpers/classCallCheck'));
var _createClass = _interopDefault(require('@babel/runtime/helpers/createClass'));
require('core-js/modules/es6.object.assign');
require('core-js/modules/web.dom.iterable');
require('core-js/modules/es6.object.freeze');
var laksaCoreCrypto = require('laksa-core-crypto');
require('core-js/modules/es6.regexp.replace');
require('core-js/modules/es6.string.repeat');
var _objectSpread = _interopDefault(require('@babel/runtime/helpers/objectSpread'));
require('core-js/modules/es6.promise');
var _regeneratorRuntime = _interopDefault(require('@babel/runtime/regenerator'));
require('regenerator-runtime/runtime');
var _asyncToGenerator = _interopDefault(require('@babel/runtime/helpers/asyncToGenerator'));
var _applyDecoratedDescriptor = _interopDefault(require('@babel/runtime/helpers/applyDecoratedDescriptor'));
var laksaCoreTransaction = require('laksa-core-transaction');
var laksaShared = require('laksa-shared');
var _toArray = _interopDefault(require('@babel/runtime/helpers/toArray'));
require('core-js/modules/es6.regexp.to-string');
var _possibleConstructorReturn = _interopDefault(require('@babel/runtime/helpers/possibleConstructorReturn'));
var _getPrototypeOf = _interopDefault(require('@babel/runtime/helpers/getPrototypeOf'));
var _assertThisInitialized = _interopDefault(require('@babel/runtime/helpers/assertThisInitialized'));
var _inherits = _interopDefault(require('@babel/runtime/helpers/inherits'));
var _defineProperty = _interopDefault(require('@babel/runtime/helpers/defineProperty'));
/**
* @var {Object<String>} Matchers
* @description Matchers object with multiple patterns
*/
var Matchers = {
ByStrX: /^ByStr[0-9]+$/,
String: /^String$/,
Uint: /^Uint(32|64|128|256)$/,
Int: /^Int(32|64|128|256)$/,
BNum: /^BNum$/
/**
* @var {Array<Object>} validators
* @description valitador objects
*/
};
var validators = [{
type: 'ByStrX',
match: function match(type) {
return Matchers.ByStrX.test(type);
},
validatorFn: function validatorFn(value) {
return laksaUtils.isByStrX.test(value);
},
transformer: function transformer(value) {
return String(value);
}
}, {
type: 'UInt',
match: function match(type) {
return Matchers.Uint.test(type);
},
validatorFn: function validatorFn(value) {
return laksaUtils.isUint.test(value);
},
transformer: function transformer(value) {
return Number(value, 10);
}
}, {
type: 'Int',
match: function match(type) {
return Matchers.Int.test(type);
},
validatorFn: function validatorFn(value) {
return laksaUtils.isInt.test(value);
},
transformer: function transformer(value) {
return Number(value, 10);
}
}, {
type: 'BNum',
match: function match(type) {
return Matchers.BNum.test(type);
},
validatorFn: function validatorFn(value) {
return laksaUtils.isBN.test(new laksaUtils.BN(value));
},
transformer: function transformer(value) {
return Number(value, 10);
}
}, {
type: 'String',
match: function match(type) {
return Matchers.String.test(type);
},
validatorFn: function validatorFn(value) {
return laksaUtils.isString.test(value);
},
transformer: function transformer(value) {
return String(value);
}
}];
/**
* @function validate
* @description validate param type and it's value
* @param {String} type - param type
* @param {any} value - param value to validate
* @return {Boolean} validate result
*/
var validate = function validate(type, value) {
return validators.some(function (val) {
return val.match(type) && val.validatorFn(value);
});
};
/**
* @function transform
* @description transform a value to it's validator format
* @param {String} type - param type
* @param {any} value - param value to validate
* @return {any} transform result
*/
var transform = function transform(type, value) {
if (validate(type, value)) {
var found = validators.find(function (d) {
return d.match(type);
});
return found.transformer(value);
} else {
throw new Error('Cannot transform');
}
};
/**
* @function getParamTypes
* @description extract param types for abi object
* @param {Array<Object>} list {description}
* @return {Array<Object>} {description}
*/
function getParamTypes(list) {
var result = [];
list.map(function (obj, index) {
result[index] = obj.type;
return false;
});
return result;
}
/**
* @class ABI
* @description ABI instance
* @param {Object} abi abi object
* @return {ABI} ABI instance
*/
var ABI =
/*#__PURE__*/
function () {
function ABI(abi) {
_classCallCheck(this, ABI);
/**
* @var {Array} events
* @memberof ABI
* @description events
*/
this.events = abi !== undefined ? abi.events : []; // Array<object>
/**
* @var {Array} fields
* @memberof ABI
* @description fields
*/
this.fields = abi !== undefined ? abi.fields : []; // Array<object>
/**
* @var {String} name
* @memberof ABI
* @description name
*/
this.name = abi !== undefined ? abi.name : ''; // string
/**
* @var {Array} params
* @memberof ABI
* @description params
*/
this.params = abi !== undefined ? abi.params : []; // Array<object>
/**
* @var {Array} transitions
* @memberof ABI
* @description transitions
*/
this.transitions = abi !== undefined ? abi.transitions : []; // Array<object>
}
/**
* @function getName
* @memberof ABI
* @description name getter
* @return {String} ABI.name
*/
_createClass(ABI, [{
key: "getName",
value: function getName() {
return this.name;
}
/**
* @function getInitParams
* @memberof ABI
* @description params getter
* @return {String} ABI.params
*/
}, {
key: "getInitParams",
value: function getInitParams() {
return this.params;
}
/**
* @function getInitParamTypes
* @memberof ABI
* @description get param types array
* @return {Array<Object>} param types
*/
}, {
key: "getInitParamTypes",
value: function getInitParamTypes() {
if (this.params.length > 0) {
return getParamTypes(this.params);
} else return [];
}
/**
* @function getFields
* @memberof ABI
* @description fields getter
* @return {Array} ABI.fields
*/
}, {
key: "getFields",
value: function getFields() {
return this.fields;
}
/**
* @function getFieldsTypes
* @memberof ABI
* @description get fields types array
* @return {Array<Object>} fields types
*/
}, {
key: "getFieldsTypes",
value: function getFieldsTypes() {
if (this.fields.length > 0) {
return getParamTypes(this.fields);
} else return [];
}
/**
* @function getTransitions
* @memberof ABI
* @description transitions getter
* @return {Array<Object>} ABI.transitions
*/
}, {
key: "getTransitions",
value: function getTransitions() {
return this.transitions;
}
/**
* @function getTransitionsParamTypes
* @memberof ABI
* @description get transitions types array
* @return {Array<Object>} transitions types
*/
}, {
key: "getTransitionsParamTypes",
value: function getTransitionsParamTypes() {
var returnArray = [];
if (this.transitions.length > 0) {
for (var i = 0; i < this.transitions.length; i += 1) {
returnArray[i] = getParamTypes(this.transitions[i].params);
}
}
return returnArray;
}
/**
* @function getEvents
* @memberof ABI
* @description events getter
* @return {Array<Object>} ABI.events
*/
}, {
key: "getEvents",
value: function getEvents() {
return this.events;
}
}]);
return ABI;
}();
/**
* @var {Object} ContractStatus
* @description immutable contract status
*/
var ContractStatus = Object.freeze({
INITIALISED: 'initialised',
TESTED: 'tested',
ERROR: 'error',
SIGNED: 'signed',
SENT: 'sent',
REJECTED: 'rejected',
DEPLOYED: 'deployed'
});
/**
* @function setParamValues
* @description set param values
* @param {Array<Object>} rawParams - init params get from ABI
* @param {Array<Object>} newValues - init params set for ABI
* @return {Array<objObjectect>} new array of params objects
*/
var setParamValues = function setParamValues(rawParams, newValues) {
var newParams = [];
rawParams.forEach(function (v, i) {
if (!validate(v.type, newValues[i].value)) {
throw new TypeError("Type validator failed,with <".concat(v.vname, ":").concat(v.type, ">"));
} // FIXME:it may change cause local scilla runner return the `name` not `vname`
// But when call or make transaction, remote node only accpet `vname`
var newObj = Object.assign({}, v, {
value: newValues[i].value,
vname: v.name ? v.name : v.vname
});
if (newObj.name) {
delete newObj.name;
}
newParams.push(newObj);
});
return newParams;
};
function getAddressForContract(tx) {
// always subtract 1 from the tx nonce, as contract addresses are computed
// based on the nonce in the global state.
var nonce = tx.txParams.nonce ? tx.txParams.nonce - 1 : 0;
return laksaCoreCrypto.hashjs.sha256().update(tx.senderAddress, 'hex').update(laksaCoreCrypto.intToHexArray(nonce, 64).join(''), 'hex').digest('hex').slice(24);
}
var _dec, _dec2, _dec3, _dec4, _class;
/**
* @class Contract
* @param {Object} params - contract params
* @param {Contracts} factory - contract factory
* @param {String} status -Contract status
* @return {Contract} Contract instance
*/
var Contract = (_dec = laksaShared.assertObject({
gasLimit: ['isLong', 'required'],
gasPrice: ['isBN', 'required'],
toDS: ['isBoolean', 'optional']
}), _dec2 = laksaShared.assertObject({
transition: ['isString', 'required'],
params: ['isArray', 'required'],
amount: ['isBN', 'optional'],
gasLimit: ['isLong', 'optional'],
gasPrice: ['isBN', 'optional'],
toDS: ['isBoolean', 'optional']
}), _dec3 = laksaShared.assertObject({
gasLimit: ['isLong', 'required'],
gasPrice: ['isBN', 'required'],
toDS: ['isBoolean', 'optional']
}), _dec4 = laksaShared.assertObject({
transition: ['isString', 'required'],
params: ['isArray', 'required'],
amount: ['isBN', 'required'],
gasLimit: ['isLong', 'required'],
gasPrice: ['isBN', 'required'],
toDS: ['isBoolean', 'optional']
}), (_class =
/*#__PURE__*/
function () {
function Contract(params, factory) {
var status = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : ContractStatus.INITIALISED;
_classCallCheck(this, Contract);
/**
* @var {String} code
* @memberof Contract.prototype
* @description code
*/
this.code = params.code || '';
/**
* @var {Array<Object>} init
* @memberof Contract.prototype
* @description init
*/
this.init = params.init || [];
/**
* @var {Number} version
* @memberof Contract.prototype
* @description version
*/
this.version = params.version || 0;
/**
* @var {String} ContractAddress
* @memberof Contract.prototype
* @description ContractAddress
*/
this.ContractAddress = params.ContractAddress || undefined;
/**
* @var {Messenger} messenger
* @memberof Contract.prototype
* @description messenger
*/
this.messenger = factory.messenger;
/**
* @var {Wallet} signer
* @memberof Contract.prototype
* @description signer
*/
this.signer = factory.signer;
/**
* @var {String} status
* @memberof Contract.prototype
* @description status
*/
this.status = status;
/**
* @var {Transaction|Object} transaction
* @memberof Contract.prototype
* @description transaction
*/
this.transaction = {};
}
/**
* @function isInitialised
* @description return true if the contract has been initialised
* @memberof Contract
* @return {Boolean}
*/
_createClass(Contract, [{
key: "isInitialised",
value: function isInitialised() {
return this.status === ContractStatus.INITIALISED;
}
/**
* @function isSigned
* @description return true if the contract has been signed
* @memberof Contract
* @return {Boolean}
*/
}, {
key: "isSigned",
value: function isSigned() {
return this.status === ContractStatus.SIGNED;
}
/**
* @function isSent
* @description return true if the contract has been sent
* @memberof Contract
* @return {Boolean}
*/
}, {
key: "isSent",
value: function isSent() {
return this.status === ContractStatus.SENT;
}
/**
* @function isDeployed
* @description return true if the contract has been deployed
* @memberof Contract
* @return {Boolean}
*/
}, {
key: "isDeployed",
value: function isDeployed() {
return this.status === ContractStatus.DEPLOYED;
}
/**
* @function isRejected
* @description return true if the contract has been rejected
* @memberof Contract
* @return {Boolean}
*/
}, {
key: "isRejected",
value: function isRejected() {
return this.status === ContractStatus.REJECTED;
}
/**
* @function deployPayload
* @description return deploy payload
* @memberof Contract
* @return {Object} Deploy payload
*/
}, {
key: "setStatus",
/**
* @function setStatus
* @description set Contract status
* @memberof Contract
* @param {String} status - contract status during all life-time
*/
value: function setStatus(status) {
this.status = status;
}
/**
* @function setInitParamsValues
* @memberof Contract
* @description set init params value and return Contract
* @param {Array<Object>} initParams - init params get from ABI
* @param {Array<Object>} arrayOfValues - init params set for ABI
* @return {Contract} - Contract instance
*/
}, {
key: "setInitParamsValues",
value: function setInitParamsValues(initParams, arrayOfValues) {
var result = setParamValues(initParams, arrayOfValues);
this.init = result;
return this;
}
/**
* @function deploy
* @memberof Contract
* @description deploy Contract with a few parameters
* @param {Object} deployObject
* @param {Long} deployObject.gasLimit - gasLimit
* @param {BN} deployObject.gasPrice -gasPrice
* @param {?Boolean} deployObject.toDS - toDS
* @param {?Account} deployObject.account - account to sign
* @param {?String} deployObject.password - account's password if it's encrypted
* @param {Number} deployObject.maxAttempts - max try when confirming transaction
* @param {Number} deployObject.interval - retry interval
* @return {Promise<Contract>} Contract with Contract Status
*/
}, {
key: "deploy",
value: function () {
var _deploy = _asyncToGenerator(
/*#__PURE__*/
_regeneratorRuntime.mark(function _callee(_ref) {
var _ref$gasLimit, gasLimit, _ref$gasPrice, gasPrice, _ref$account, account, password, _ref$maxAttempts, maxAttempts, _ref$interval, interval, _ref$toDS, toDS;
return _regeneratorRuntime.wrap(function _callee$(_context) {
while (1) {
switch (_context.prev = _context.next) {
case 0:
_ref$gasLimit = _ref.gasLimit, gasLimit = _ref$gasLimit === void 0 ? laksaUtils.Long.fromNumber(2500) : _ref$gasLimit, _ref$gasPrice = _ref.gasPrice, gasPrice = _ref$gasPrice === void 0 ? new laksaUtils.BN(100) : _ref$gasPrice, _ref$account = _ref.account, account = _ref$account === void 0 ? this.signer.signer : _ref$account, password = _ref.password, _ref$maxAttempts = _ref.maxAttempts, maxAttempts = _ref$maxAttempts === void 0 ? 20 : _ref$maxAttempts, _ref$interval = _ref.interval, interval = _ref$interval === void 0 ? 1000 : _ref$interval, _ref$toDS = _ref.toDS, toDS = _ref$toDS === void 0 ? false : _ref$toDS;
if (!(!this.code || !this.init)) {
_context.next = 3;
break;
}
throw new Error('Cannot deploy without code or ABI.');
case 3:
_context.prev = 3;
this.setDeployPayload({
gasLimit: gasLimit,
gasPrice: gasPrice,
toDS: toDS
});
_context.next = 7;
return this.sendContract({
account: account,
password: password
});
case 7:
_context.next = 9;
return this.confirmTx(maxAttempts, interval);
case 9:
return _context.abrupt("return", this);
case 12:
_context.prev = 12;
_context.t0 = _context["catch"](3);
throw _context.t0;
case 15:
case "end":
return _context.stop();
}
}
}, _callee, this, [[3, 12]]);
}));
function deploy(_x) {
return _deploy.apply(this, arguments);
}
return deploy;
}()
/**
* @function call
* @memberof Contract
* @description call a deployed contract with a set of parameters
* @param {Object} callObject
* @param {String} callObject.transition - transition name defined by smart contract
* @param {Array<Object>} callObject.params -array of params send to transition
* @param {?BN} callObject.amount - call amount
* @param {?Boolean} callObject.toDS - toDS
* @param {?Account} callObject.account - account to sign
* @param {?String} callObject.password - account's password if it's encrypted
* @param {Number} callObject.maxAttempts - max try when confirming transaction
* @param {Number} callObject.interval - retry interval
* @return {Promise<Contract>}
*/
}, {
key: "call",
value: function () {
var _call = _asyncToGenerator(
/*#__PURE__*/
_regeneratorRuntime.mark(function _callee2(_ref2) {
var transition, params, _ref2$amount, amount, _ref2$gasLimit, gasLimit, _ref2$gasPrice, gasPrice, _ref2$account, account, password, _ref2$maxAttempts, maxAttempts, _ref2$interval, interval, _ref2$toDS, toDS;
return _regeneratorRuntime.wrap(function _callee2$(_context2) {
while (1) {
switch (_context2.prev = _context2.next) {
case 0:
transition = _ref2.transition, params = _ref2.params, _ref2$amount = _ref2.amount, amount = _ref2$amount === void 0 ? new laksaUtils.BN(0) : _ref2$amount, _ref2$gasLimit = _ref2.gasLimit, gasLimit = _ref2$gasLimit === void 0 ? laksaUtils.Long.fromNumber(1000) : _ref2$gasLimit, _ref2$gasPrice = _ref2.gasPrice, gasPrice = _ref2$gasPrice === void 0 ? new laksaUtils.BN(100) : _ref2$gasPrice, _ref2$account = _ref2.account, account = _ref2$account === void 0 ? this.signer.signer : _ref2$account, password = _ref2.password, _ref2$maxAttempts = _ref2.maxAttempts, maxAttempts = _ref2$maxAttempts === void 0 ? 20 : _ref2$maxAttempts, _ref2$interval = _ref2.interval, interval = _ref2$interval === void 0 ? 1000 : _ref2$interval, _ref2$toDS = _ref2.toDS, toDS = _ref2$toDS === void 0 ? false : _ref2$toDS;
if (this.ContractAddress) {
_context2.next = 3;
break;
}
return _context2.abrupt("return", Promise.reject(Error('Contract has not been deployed!')));
case 3:
_context2.prev = 3;
this.setCallPayload({
transition: transition,
params: params,
amount: amount,
gasLimit: gasLimit,
gasPrice: gasPrice,
toDS: toDS
});
_context2.next = 7;
return this.sendContract({
account: account,
password: password
});
case 7:
_context2.next = 9;
return this.confirmTx(maxAttempts, interval);
case 9:
return _context2.abrupt("return", this);
case 12:
_context2.prev = 12;
_context2.t0 = _context2["catch"](3);
throw _context2.t0;
case 15:
case "end":
return _context2.stop();
}
}
}, _callee2, this, [[3, 12]]);
}));
function call(_x2) {
return _call.apply(this, arguments);
}
return call;
}()
/**
* @function sendContract
* @memberof Contract
* @description send contract with account and password
* @param {Object} paramObject
* @param {Account} paramObject.account - Account to sign
* @param {String} paramObject.password - Account's password if it is encrypted
* @return {Promise<Contract>} Contract instance
*/
}, {
key: "sendContract",
value: function () {
var _sendContract = _asyncToGenerator(
/*#__PURE__*/
_regeneratorRuntime.mark(function _callee3(_ref3) {
var _ref3$account, account, password, _ref4, transaction, response;
return _regeneratorRuntime.wrap(function _callee3$(_context3) {
while (1) {
switch (_context3.prev = _context3.next) {
case 0:
_ref3$account = _ref3.account, account = _ref3$account === void 0 ? this.signer.signer : _ref3$account, password = _ref3.password;
_context3.prev = 1;
_context3.next = 4;
return this.signTxn({
account: account,
password: password
});
case 4:
_context3.next = 6;
return this.transaction.sendTransaction();
case 6:
_ref4 = _context3.sent;
transaction = _ref4.transaction;
response = _ref4.response;
this.ContractAddress = laksaCoreCrypto.getAddress(this.ContractAddress || response.ContractAddress || getAddressForContract(transaction), undefined, laksaCoreCrypto.AddressType.checkSum);
this.transaction = transaction.map(function (obj) {
return _objectSpread({}, obj, {
TranID: response.TranID
});
});
this.setStatus(ContractStatus.SENT);
return _context3.abrupt("return", this);
case 15:
_context3.prev = 15;
_context3.t0 = _context3["catch"](1);
throw _context3.t0;
case 18:
case "end":
return _context3.stop();
}
}
}, _callee3, this, [[1, 15]]);
}));
function sendContract(_x3) {
return _sendContract.apply(this, arguments);
}
return sendContract;
}()
/**
* @function signTxn
* @memberof Contract
* @description sign contract with account and password
* @param {Object} paramObject
* @param {Account} paramObject.account - Account to sign
* @param {String} paramObject.password - Account's password if it is encrypted
* @return {Promise<Contract>} Contract instance
*/
}, {
key: "signTxn",
value: function () {
var _signTxn = _asyncToGenerator(
/*#__PURE__*/
_regeneratorRuntime.mark(function _callee4(_ref5) {
var _ref5$account, account, password;
return _regeneratorRuntime.wrap(function _callee4$(_context4) {
while (1) {
switch (_context4.prev = _context4.next) {
case 0:
_ref5$account = _ref5.account, account = _ref5$account === void 0 ? this.signer.signer : _ref5$account, password = _ref5.password;
_context4.prev = 1;
_context4.next = 4;
return account.signTransaction(this.transaction, password);
case 4:
this.transaction = _context4.sent;
this.setStatus(ContractStatus.SIGNED);
return _context4.abrupt("return", this);
case 9:
_context4.prev = 9;
_context4.t0 = _context4["catch"](1);
throw _context4.t0;
case 12:
case "end":
return _context4.stop();
}
}
}, _callee4, this, [[1, 9]]);
}));
function signTxn(_x4) {
return _signTxn.apply(this, arguments);
}
return signTxn;
}()
/**
* @function confirmTx
* @memberof Contract
* @description confirm transaction with maxAttempts and intervel
* @param {Number} maxAttempts - max tries
* @param {Number} interval - try confirm intervally
* @return {Promise<Contract>} Contract instance
*/
}, {
key: "confirmTx",
value: function () {
var _confirmTx = _asyncToGenerator(
/*#__PURE__*/
_regeneratorRuntime.mark(function _callee5() {
var maxAttempts,
interval,
_args5 = arguments;
return _regeneratorRuntime.wrap(function _callee5$(_context5) {
while (1) {
switch (_context5.prev = _context5.next) {
case 0:
maxAttempts = _args5.length > 0 && _args5[0] !== undefined ? _args5[0] : 20;
interval = _args5.length > 1 && _args5[1] !== undefined ? _args5[1] : 1000;
_context5.prev = 2;
_context5.next = 5;
return this.transaction.confirm(this.transaction.TranID, maxAttempts, interval);
case 5:
if (!(!this.transaction.receipt || !this.transaction.receipt.success)) {
_context5.next = 8;
break;
}
this.setStatus(ContractStatus.REJECTED);
return _context5.abrupt("return", this);
case 8:
this.setStatus(ContractStatus.DEPLOYED);
return _context5.abrupt("return", this);
case 12:
_context5.prev = 12;
_context5.t0 = _context5["catch"](2);
throw _context5.t0;
case 15:
case "end":
return _context5.stop();
}
}
}, _callee5, this, [[2, 12]]);
}));
function confirmTx() {
return _confirmTx.apply(this, arguments);
}
return confirmTx;
}()
/**
* @function getState
* @memberof Contract
* @description get smart contract state
* @return {Object} - RPC response
*/
}, {
key: "getState",
value: function () {
var _getState = _asyncToGenerator(
/*#__PURE__*/
_regeneratorRuntime.mark(function _callee6() {
var response;
return _regeneratorRuntime.wrap(function _callee6$(_context6) {
while (1) {
switch (_context6.prev = _context6.next) {
case 0:
if (!(this.status !== ContractStatus.DEPLOYED)) {
_context6.next = 2;
break;
}
return _context6.abrupt("return", Promise.resolve([]));
case 2:
_context6.next = 4;
return this.messenger.send('GetSmartContractState', this.ContractAddress);
case 4:
response = _context6.sent;
return _context6.abrupt("return", response);
case 6:
case "end":
return _context6.stop();
}
}
}, _callee6, this);
}));
function getState() {
return _getState.apply(this, arguments);
}
return getState;
}()
}, {
key: "getInit",
value: function () {
var _getInit = _asyncToGenerator(
/*#__PURE__*/
_regeneratorRuntime.mark(function _callee7() {
var response;
return _regeneratorRuntime.wrap(function _callee7$(_context7) {
while (1) {
switch (_context7.prev = _context7.next) {
case 0:
if (!(this.status !== ContractStatus.DEPLOYED)) {
_context7.next = 2;
break;
}
return _context7.abrupt("return", Promise.resolve([]));
case 2:
_context7.next = 4;
return this.messenger.send('GetSmartContractInit', this.ContractAddress);
case 4:
response = _context7.sent;
return _context7.abrupt("return", response.result);
case 6:
case "end":
return _context7.stop();
}
}
}, _callee7, this);
}));
function getInit() {
return _getInit.apply(this, arguments);
}
return getInit;
}()
/**
* @function setDeployPayload
* @memberof Contract
* @description set deploy payload
* @param {Object} deployObject
* @param {Long} deployObject.gasLimit - gas limit
* @param {BN} deployObject.gasPrice - gas price
* @param {Boolean} deployObject.toDS - if send to shard
* @return {Contract} Contract instance
*/
}, {
key: "setDeployPayload",
value: function setDeployPayload(_ref6) {
var gasPrice = _ref6.gasPrice,
gasLimit = _ref6.gasLimit,
toDS = _ref6.toDS;
this.transaction = new laksaCoreTransaction.Transaction(_objectSpread({}, this.deployPayload, {
gasPrice: gasPrice,
gasLimit: gasLimit
}), this.messenger, laksaCoreTransaction.TxStatus.Initialised, toDS);
return this;
}
/**
* @function setCallPayload
* @memberof Contract
* @description set call contract payload
* @param {Object} callObject
* @param {String} callObject.transition - transition name defined by smart contract
* @param {Array<Object>} callObject.params -array of params send to transition
* @param {?BN} callObject.amount - call amount
* @param {Long} callObject.gasLimit - gas limit
* @param {BN} callObject.gasPrice - gas price
* @param {Boolean} callObject.toDS - if send to shard
* @return {Contract} Contract instance
*/
}, {
key: "setCallPayload",
value: function setCallPayload(_ref7) {
var transition = _ref7.transition,
params = _ref7.params,
amount = _ref7.amount,
gasLimit = _ref7.gasLimit,
gasPrice = _ref7.gasPrice,
toDS = _ref7.toDS;
var msg = {
_tag: transition,
// TODO: this should be string, but is not yet supported by lookup.
params: params
};
this.transaction = new laksaCoreTransaction.Transaction(_objectSpread({}, this.callPayload, {
amount: amount,
gasPrice: gasPrice,
gasLimit: gasLimit,
data: JSON.stringify(msg)
}), this.messenger, laksaCoreTransaction.TxStatus.Initialised, toDS);
return this;
}
}, {
key: "deployPayload",
get: function get() {
return {
version: this.version < 65535 ? this.messenger.setTransactionVersion(this.version, this.messenger.Network_ID) : this.version,
amount: new laksaUtils.BN(0),
toAddr: laksaCoreCrypto.getAddress(String(0).repeat(40), undefined, laksaCoreCrypto.AddressType.checkSum),
code: this.code,
data: JSON.stringify(this.init).replace(/\\"/g, '"')
};
}
/**
* @function callPayload
* @description return deploy payload
* @memberof Contract
* @return {Object} call payload
*/
}, {
key: "callPayload",
get: function get() {
return {
version: this.version < 65535 ? this.messenger.setTransactionVersion(this.version, this.messenger.Network_ID) : this.version,
toAddr: laksaCoreCrypto.getAddress(this.ContractAddress, undefined, laksaCoreCrypto.AddressType.checkSum)
};
}
}]);
return Contract;
}(), (_applyDecoratedDescriptor(_class.prototype, "deploy", [_dec], Object.getOwnPropertyDescriptor(_class.prototype, "deploy"), _class.prototype), _applyDecoratedDescriptor(_class.prototype, "call", [_dec2], Object.getOwnPropertyDescriptor(_class.prototype, "call"), _class.prototype), _applyDecoratedDescriptor(_class.prototype, "setDeployPayload", [_dec3], Object.getOwnPropertyDescriptor(_class.prototype, "setDeployPayload"), _class.prototype), _applyDecoratedDescriptor(_class.prototype, "setCallPayload", [_dec4], Object.getOwnPropertyDescriptor(_class.prototype, "setCallPayload"), _class.prototype)), _class));
var _dec$1, _dec2$1, _class$1;
var TestScilla = (_dec$1 = laksaShared.assertObject({
code: ['isString', 'required']
}), _dec2$1 = laksaShared.assertObject({
code: ['isString', 'required']
}), (_class$1 =
/*#__PURE__*/
function (_Contract) {
_inherits(TestScilla, _Contract);
/**
* @var {Array<Object>}blockchain
* @memberof TestScilla.prototype
* @description Create a Contract
*/
function TestScilla() {
var _getPrototypeOf2;
var _this;
_classCallCheck(this, TestScilla);
for (var _len = arguments.length, props = new Array(_len), _key = 0; _key < _len; _key++) {
props[_key] = arguments[_key];
}
_this = _possibleConstructorReturn(this, (_getPrototypeOf2 = _getPrototypeOf(TestScilla)).call.apply(_getPrototypeOf2, [this].concat(props)));
_defineProperty(_assertThisInitialized(_this), "blockchain", []);
return _this;
}
/**
* @function testCall
* @memberof TestScilla
* @description a Test Contract instance
* @param {BN} gasLimit - gasLimit for test call to scilla-runner
* @return {TestScilla} raw Contract object
*/
_createClass(TestScilla, [{
key: "testCall",
value: function () {
var _testCall = _asyncToGenerator(
/*#__PURE__*/
_regeneratorRuntime.mark(function _callee(gasLimit) {
var callContractJson, result;
return _regeneratorRuntime.wrap(function _callee$(_context) {
while (1) {
switch (_context.prev = _context.next) {
case 0:
_context.prev = 0;
callContractJson = {
code: this.code,
init: JSON.stringify(this.init),
blockchain: JSON.stringify(this.blockchain),
gaslimit: JSON.stringify(gasLimit) // the endpoint for sendServer has been set to scillaProvider
};
_context.next = 4;
return this.messenger.sendServer('/contract/call', callContractJson);
case 4:
result = _context.sent;
if (result.result) {
this.setStatus(ContractStatus.TESTED);
} else {
this.setStatus(ContractStatus.ERROR);
}
return _context.abrupt("return", this);
case 9:
_context.prev = 9;
_context.t0 = _context["catch"](0);
throw _context.t0;
case 12:
case "end":
return _context.stop();
}
}
}, _callee, this, [[0, 9]]);
}));
function testCall(_x) {
return _testCall.apply(this, arguments);
}
return testCall;
}()
/**
* @function getABI
* @memberof TestScilla
* @description get ABI from scilla runner
* @param {Object} params
* @param {String} params.code - code string
* @return {Object} RPC result
*/
}, {
key: "getABI",
value: function () {
var _getABI = _asyncToGenerator(
/*#__PURE__*/
_regeneratorRuntime.mark(function _callee2(_ref) {
var code, result;
return _regeneratorRuntime.wrap(function _callee2$(_context2) {
while (1) {
switch (_context2.prev = _context2.next) {
case 0:
code = _ref.code;
_context2.prev = 1;
_context2.next = 4;
return this.messenger.sendServer('/contract/check', {
code: code
});
case 4:
result = _context2.sent;
if (!(result.result && result.message !== undefined)) {
_context2.next = 7;
break;
}
return _context2.abrupt("return", JSON.parse(result.message));
case 7:
_context2.next = 12;
break;
case 9:
_context2.prev = 9;
_context2.t0 = _context2["catch"](1);
throw _context2.t0;
case 12:
case "end":
return _context2.stop();
}
}
}, _callee2, this, [[1, 9]]);
}));
function getABI(_x2) {
return _getABI.apply(this, arguments);
}
return getABI;
}()
/**
* @function decodeABI
* @description decode ABI from scilla runner
* @param {Object} paramObject
* @param {String} paramObject.code - scilla code string
* @return {TestScilla} test contract
*/
}, {
key: "decodeABI",
value: function () {
var _decodeABI = _asyncToGenerator(
/*#__PURE__*/
_regeneratorRuntime.mark(function _callee3(_ref2) {
var code, abiObj;
return _regeneratorRuntime.wrap(function _callee3$(_context3) {
while (1) {
switch (_context3.prev = _context3.next) {
case 0:
code = _ref2.code;
_context3.prev = 1;
this.setCode(code);
_context3.next = 5;
return this.getABI({
code: code
});
case 5:
abiObj = _context3.sent;
this.setABI(abiObj);
return _context3.abrupt("return", this);
case 10:
_context3.prev = 10;
_context3.t0 = _context3["catch"](1);
throw _context3.t0;
case 13:
case "end":
return _context3.stop();
}
}
}, _callee3, this, [[1, 10]]);
}));
function decodeABI(_x3) {
return _decodeABI.apply(this, arguments);
}
return decodeABI;
}()
/**
* @function setBlockNumber
* @memberof TestScilla
* @description set block number for TestScilla
* @param {Number} number - block number setted to blockchain
* @return {TestScilla|false} test contract
*/
}, {
key: "setBlockNumber",
value: function () {
var _setBlockNumber = _asyncToGenerator(
/*#__PURE__*/
_regeneratorRuntime.mark(function _callee4(number) {
var result;
return _regeneratorRuntime.wrap(function _callee4$(_context4) {
while (1) {
switch (_context4.prev = _context4.next) {
case 0:
_context4.prev = 0;
if (!(number && laksaUtils.isInt(Number(number)))) {
_context4.next = 7;
break;
}
this.setBlockchain(String(number));
this.setCreationBlock(String(number));
return _context4.abrupt("return", this);
case 7:
if (!(number === undefined)) {
_context4.next = 15;
break;
}
_context4.next = 10;
return this.messenger.send('GetLatestTxBlock');
case 10:
result = _context4.sent;
if (!result) {
_context4.next = 15;
break;
}
this.setBlockchain(result.header.BlockNum);
this.setCreationBlock(result.header.BlockNum);
return _context4.abrupt("return", this);
case 15:
_context4.next = 20;
break;
case 17:
_context4.prev = 17;
_context4.t0 = _context4["catch"](0);
throw _context4.t0;
case 20:
case "end":
return _context4.stop();
}
}
}, _callee4, this, [[0, 17]]);
}));
function setBlockNumber(_x4) {
return _setBlockNumber.apply(this, arguments);
}
return setBlockNumber;
}()
/**
* @function testPayload
* @memberof TestScilla.prototype
* @description construct payload for TestScilla
* @return {Object} payload object
*/
}, {
key: "setABI",
/**
* @function setABI
* @memberof TestScilla
* @description set abi for TestScilla
* @return {TestScilla} TestScilla instance
*/
value: function setABI(abi) {
this.abi = new ABI(abi) || {};
return this;
}
/**
* @function setCode
* @memberof TestScilla
* @description set code for TestScilla
* @return {TestScilla} test contract
*/
}, {
key: "setCode",
value: function setCode(code) {
this.code = code || '';
return this;
}
/**
* @function setInitParamsValues
* @memberof TestScilla
* @description set init param values for TestScilla
* @param {Array<Object>} initParams - init params get from ABI
* @param {Array<Object>} arrayOfValues - init params set for ABI
* @return {TestScilla} test contract
*/
}, {
key: "setInitParamsValues",
value: function setInitParamsValues(initParams, arrayOfValues) {
var result = setParamValues(initParams, arrayOfValues);
this.init = result;
return this;
}
/**
* @function setCreationBlock
* @memberof TestScilla
* @description set creation Block for TestScilla
* @param {Number} blockNumber - block number for blockchain
* @return {TestScilla} test contract
*/
}, {
key: "setCreationBlock",
value: function setCreationBlock(blockNumber) {
var result = setParamValues([{
vname: '_creation_block',
type: 'BNum'
}], [{
vname: '_creation_block',
type: 'BNum',
value: new laksaUtils.BN(blockNumber).toString()
}]);
var _this$init = _toArray(this.init),
arr = _this$init.slice(0);
arr.push(result[0]);
this.init = arr;
return this;
}
/**
* @function setBlockchain
* @memberof TestScilla
* @description set blockchain object for TestScilla
* @param {Number} blockNumber - block number for blockchain
* @return {TestScilla} test contract
*/
}, {
key: "setBlockchain",
value: function setBlockchain(blockNumber) {
var result = setParamValues([{
vname: 'BLOCKNUMBER',
type: 'BNum'
}], [{
vname: 'BLOCKNUMBER',
type: 'BNum',
value: new laksaUtils.BN(blockNumber).toString()
}]);
var _this$blockchain = _toArray(this.blockchain),
arr = _this$blockchain.slice(0);
arr.push(result[0]);
this.blockchain = arr;
return this;
}
}, {
key: "testPayload",
get: function get() {
return _objectSpread({}, this.payload(), {
code: this.code,
data: JSON.stringify(this.init.concat(this.blockchain)).replace(/\\"/g, '"')
});
}
}]);
return TestScilla;
}(Contract), (_applyDecoratedDescriptor(_class$1.prototype, "getABI", [_dec$1], Object.getOwnPropertyDescriptor(_class$1.prototype, "getABI"), _class$1.prototype), _applyDecoratedDescriptor(_class$1.prototype, "decodeABI", [_dec2$1], Object.getOwnPropertyDescriptor(_class$1.prototype, "decodeABI"), _class$1.prototype)), _class$1));
var _dec$2, _class$2;
/**
* @class Contracts
* @param {Messenger} messenger - Messenger instance
* @param {Wallet} signer - Wallet instance
* @return {Contracts} Contract factory
*/
var Contracts = (_dec$2 = laksaShared.assertObject({
ContractAddress: ['isAddress', 'optional'],
code: ['isString', 'optional'],
init: ['isArray', 'optional'],
status: ['isString', 'optional']
}), (_class$2 =
/*#__PURE__*/
function (_Core) {
_inherits(Contracts, _Core);
function Contracts(messenger, signer) {
var _this;
_classCallCheck(this, Contracts);
_this = _possibleConstructorReturn(this, _getPrototypeOf(Contracts).call(this));
/**
* @var {Messeger} messenger
* @memberof Contracts.prototype
* @description Messenger instance
*/
_this.messenger = messenger;
/**
* @var {Wallet} signer
* @memberof Contracts.prototype
* @description Wallet instance
*/
_this.signer = signer;
return _this;
}
/**
* @function getAddressForContract
* @memberof Contracts
* @description get Contract address from Transaction
* @param {Transaction} tx - Transaction instance
* @return {String} Contract address
*/
_createClass(Contracts, [{
key: "getAddressForContract",
value: function getAddressForContract$$1(tx) {
// always subtract 1 from the tx nonce, as contract addresses are computed
// based on the nonce in the global state.
return laksaCoreCrypto.getAddress(getAddressForContract(tx), undefined, laksaCoreCrypto.AddressType.checkSum);
}
/**
* @function new
* @memberof Contracts
* @description Create a Contract
* @param {String} code - Code string
* @param {Array<Object>} init - init params
* @return {Contract} Contract instance
*/
}, {
key: "new",
value: function _new(code, init) {
var newContract = new Contract({
code: code,
init: init
}, {
messenger: this.messenger,
signer: this.signer
}, ContractStatus.INITIALISED);
return newContract;
}
/**
* @function at
* @memberof Contracts
* @description get a Contract from factory and give it Messenger and Wallet as members
* @param {Contract} contract - Contract instance
* @return {Contract} Contract instance
*/
}, {
key: "at",
value: function at(contract) {
return new Contract(_objectSpread({}, contract), {
messenger: this.messenger,
signer: this.signer
}, contract.status);
}
/**
* @function testContract
* @memberof Contracts
* @description test Contract code and init params, usable before deploying
* @param {String} code - Code string
* @param {Array<Object>} init - init params
* @return {Boolean} test result boolean
*/
}, {
key: "testContract",
value: function () {
var _testContract = _asyncToGenerator(
/*#__PURE__*/
_regeneratorRuntime.mark(function _callee(code, init) {
var contract, result;
return _regeneratorRuntime.wrap(function _callee$(_context) {
while (1) {
switch (_context.prev = _context.next) {
case 0:
contract = new TestScilla({
code: code,
init: init
}, {
messenger: this.messenger,
signer: this.signer
}, ContractStatus.INITIALISED);
_context.next = 3;
return contract // decode ABI from code first
.decodeABI({
code: code
}) // we set the init params to decoded ABI
.then(function (decoded) {
return decoded.setInitParamsValues(decoded.abi.getInitParams(), init);
}) // we get the current block number from node, and set it to params
.then(function (inited) {
return inited.setBlockNumber();
}) // but we have to give i