laksa-core-contract
Version:
Contract instance for laksa
1,202 lines (1,051 loc) • 35.1 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.
*/
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('laksa-utils'), require('laksa-core-crypto'), require('laksa-core-transaction'), require('laksa-shared')) :
typeof define === 'function' && define.amd ? define(['exports', 'laksa-utils', 'laksa-core-crypto', 'laksa-core-transaction', 'laksa-shared'], factory) :
(factory((global.Laksa = {}),global.laksaUtils,global.laksaCoreCrypto,global.laksaCoreTransaction,global.laksaShared));
}(this, (function (exports,laksaUtils,laksaCoreCrypto,laksaCoreTransaction,laksaShared) { 'use strict';
/**
* @var {Object<String>} Matchers
* @description Matchers object with multiple patterns
*/
const 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
*/
};
const validators = [{
type: 'ByStrX',
match: type => Matchers.ByStrX.test(type),
validatorFn: value => laksaUtils.isByStrX.test(value),
transformer: value => String(value)
}, {
type: 'UInt',
match: type => Matchers.Uint.test(type),
validatorFn: value => laksaUtils.isUint.test(value),
transformer: value => Number(value, 10)
}, {
type: 'Int',
match: type => Matchers.Int.test(type),
validatorFn: value => laksaUtils.isInt.test(value),
transformer: value => Number(value, 10)
}, {
type: 'BNum',
match: type => Matchers.BNum.test(type),
validatorFn: value => laksaUtils.isBN.test(new laksaUtils.BN(value)),
transformer: value => Number(value, 10)
}, {
type: 'String',
match: type => Matchers.String.test(type),
validatorFn: value => laksaUtils.isString.test(value),
transformer: value => 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
*/
const validate = (type, value) => {
return validators.some(val => 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
*/
const transform = (type, value) => {
if (validate(type, value)) {
const found = validators.find(d => 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) {
const result = [];
list.map((obj, index) => {
result[index] = obj.type;
return false;
});
return result;
}
/**
* @class ABI
* @description ABI instance
* @param {Object} abi abi object
* @return {ABI} ABI instance
*/
class ABI {
constructor(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
*/
getName() {
return this.name;
}
/**
* @function getInitParams
* @memberof ABI
* @description params getter
* @return {String} ABI.params
*/
getInitParams() {
return this.params;
}
/**
* @function getInitParamTypes
* @memberof ABI
* @description get param types array
* @return {Array<Object>} param types
*/
getInitParamTypes() {
if (this.params.length > 0) {
return getParamTypes(this.params);
} else return [];
}
/**
* @function getFields
* @memberof ABI
* @description fields getter
* @return {Array} ABI.fields
*/
getFields() {
return this.fields;
}
/**
* @function getFieldsTypes
* @memberof ABI
* @description get fields types array
* @return {Array<Object>} fields types
*/
getFieldsTypes() {
if (this.fields.length > 0) {
return getParamTypes(this.fields);
} else return [];
}
/**
* @function getTransitions
* @memberof ABI
* @description transitions getter
* @return {Array<Object>} ABI.transitions
*/
getTransitions() {
return this.transitions;
}
/**
* @function getTransitionsParamTypes
* @memberof ABI
* @description get transitions types array
* @return {Array<Object>} transitions types
*/
getTransitionsParamTypes() {
const returnArray = [];
if (this.transitions.length > 0) {
for (let 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
*/
getEvents() {
return this.events;
}
}
function _defineProperty(obj, key, value) {
if (key in obj) {
Object.defineProperty(obj, key, {
value: value,
enumerable: true,
configurable: true,
writable: true
});
} else {
obj[key] = value;
}
return obj;
}
function _objectSpread(target) {
for (var i = 1; i < arguments.length; i++) {
var source = arguments[i] != null ? arguments[i] : {};
var ownKeys = Object.keys(source);
if (typeof Object.getOwnPropertySymbols === 'function') {
ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function (sym) {
return Object.getOwnPropertyDescriptor(source, sym).enumerable;
}));
}
ownKeys.forEach(function (key) {
_defineProperty(target, key, source[key]);
});
}
return target;
}
function _applyDecoratedDescriptor(target, property, decorators, descriptor, context) {
var desc = {};
Object['ke' + 'ys'](descriptor).forEach(function (key) {
desc[key] = descriptor[key];
});
desc.enumerable = !!desc.enumerable;
desc.configurable = !!desc.configurable;
if ('value' in desc || desc.initializer) {
desc.writable = true;
}
desc = decorators.slice().reverse().reduce(function (desc, decorator) {
return decorator(target, property, desc) || desc;
}, desc);
if (context && desc.initializer !== void 0) {
desc.value = desc.initializer ? desc.initializer.call(context) : void 0;
desc.initializer = undefined;
}
if (desc.initializer === void 0) {
Object['define' + 'Property'](target, property, desc);
desc = null;
}
return desc;
}
/**
* @var {Object} ContractStatus
* @description immutable contract status
*/
const 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
*/
const setParamValues = (rawParams, newValues) => {
const newParams = [];
rawParams.forEach((v, i) => {
if (!validate(v.type, newValues[i].value)) {
throw new TypeError(`Type validator failed,with <${v.vname}:${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`
const 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.
const 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
*/
let 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 = class Contract {
constructor(params, factory, status = ContractStatus.INITIALISED) {
/**
* @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}
*/
isInitialised() {
return this.status === ContractStatus.INITIALISED;
}
/**
* @function isSigned
* @description return true if the contract has been signed
* @memberof Contract
* @return {Boolean}
*/
isSigned() {
return this.status === ContractStatus.SIGNED;
}
/**
* @function isSent
* @description return true if the contract has been sent
* @memberof Contract
* @return {Boolean}
*/
isSent() {
return this.status === ContractStatus.SENT;
}
/**
* @function isDeployed
* @description return true if the contract has been deployed
* @memberof Contract
* @return {Boolean}
*/
isDeployed() {
return this.status === ContractStatus.DEPLOYED;
}
/**
* @function isRejected
* @description return true if the contract has been rejected
* @memberof Contract
* @return {Boolean}
*/
isRejected() {
return this.status === ContractStatus.REJECTED;
}
/**
* @function deployPayload
* @description return deploy payload
* @memberof Contract
* @return {Object} Deploy payload
*/
get deployPayload() {
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
*/
get callPayload() {
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)
};
}
/**
* @function setStatus
* @description set Contract status
* @memberof Contract
* @param {String} status - contract status during all life-time
*/
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
*/
setInitParamsValues(initParams, arrayOfValues) {
const 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
*/
async deploy({
gasLimit = laksaUtils.Long.fromNumber(2500),
gasPrice = new laksaUtils.BN(100),
account = this.signer.signer,
password,
maxAttempts = 20,
interval = 1000,
toDS = false
}) {
if (!this.code || !this.init) {
throw new Error('Cannot deploy without code or ABI.');
}
try {
this.setDeployPayload({
gasLimit,
gasPrice,
toDS
});
await this.sendContract({
account,
password
});
await this.confirmTx(maxAttempts, interval);
return this;
} catch (err) {
throw err;
}
}
/**
* @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>}
*/
async call({
transition,
params,
amount = new laksaUtils.BN(0),
gasLimit = laksaUtils.Long.fromNumber(1000),
gasPrice = new laksaUtils.BN(100),
account = this.signer.signer,
password,
maxAttempts = 20,
interval = 1000,
toDS = false
}) {
if (!this.ContractAddress) {
return Promise.reject(Error('Contract has not been deployed!'));
}
try {
this.setCallPayload({
transition,
params,
amount,
gasLimit,
gasPrice,
toDS
});
await this.sendContract({
account,
password
});
await this.confirmTx(maxAttempts, interval);
return this;
} catch (err) {
throw err;
}
}
/**
* @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
*/
async sendContract({
account = this.signer.signer,
password
}) {
try {
await this.signTxn({
account,
password
});
const {
transaction,
response
} = await this.transaction.sendTransaction();
this.ContractAddress = laksaCoreCrypto.getAddress(this.ContractAddress || response.ContractAddress || getAddressForContract(transaction), undefined, laksaCoreCrypto.AddressType.checkSum);
this.transaction = transaction.map(obj => {
return _objectSpread({}, obj, {
TranID: response.TranID
});
});
this.setStatus(ContractStatus.SENT);
return this;
} catch (error) {
throw error;
}
}
/**
* @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
*/
async signTxn({
account = this.signer.signer,
password
}) {
try {
this.transaction = await account.signTransaction(this.transaction, password);
this.setStatus(ContractStatus.SIGNED);
return this;
} catch (error) {
throw error;
}
}
/**
* @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
*/
async confirmTx(maxAttempts = 20, interval = 1000) {
try {
await this.transaction.confirm(this.transaction.TranID, maxAttempts, interval);
if (!this.transaction.receipt || !this.transaction.receipt.success) {
this.setStatus(ContractStatus.REJECTED);
return this;
}
this.setStatus(ContractStatus.DEPLOYED);
return this;
} catch (error) {
throw error;
}
}
/**
* @function getState
* @memberof Contract
* @description get smart contract state
* @return {Object} - RPC response
*/
async getState() {
if (this.status !== ContractStatus.DEPLOYED) {
return Promise.resolve([]);
}
const response = await this.messenger.send('GetSmartContractState', this.ContractAddress);
return response;
}
async getInit() {
if (this.status !== ContractStatus.DEPLOYED) {
return Promise.resolve([]);
}
const response = await this.messenger.send('GetSmartContractInit', this.ContractAddress);
return response.result;
}
/**
* @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
*/
setDeployPayload({
gasPrice,
gasLimit,
toDS
}) {
this.transaction = new laksaCoreTransaction.Transaction(_objectSpread({}, this.deployPayload, {
gasPrice,
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
*/
setCallPayload({
transition,
params,
amount,
gasLimit,
gasPrice,
toDS
}) {
const msg = {
_tag: transition,
// TODO: this should be string, but is not yet supported by lookup.
params
};
this.transaction = new laksaCoreTransaction.Transaction(_objectSpread({}, this.callPayload, {
amount,
gasPrice,
gasLimit,
data: JSON.stringify(msg)
}), this.messenger, laksaCoreTransaction.TxStatus.Initialised, toDS);
return this;
}
}, (_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;
let TestScilla = (_dec$1 = laksaShared.assertObject({
code: ['isString', 'required']
}), _dec2$1 = laksaShared.assertObject({
code: ['isString', 'required']
}), (_class$1 = class TestScilla extends Contract {
/**
* @var {Array<Object>}blockchain
* @memberof TestScilla.prototype
* @description Create a Contract
*/
constructor(...props) {
super(...props);
_defineProperty(this, "blockchain", []);
}
/**
* @function testCall
* @memberof TestScilla
* @description a Test Contract instance
* @param {BN} gasLimit - gasLimit for test call to scilla-runner
* @return {TestScilla} raw Contract object
*/
async testCall(gasLimit) {
try {
const 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
};
const result = await this.messenger.sendServer('/contract/call', callContractJson);
if (result.result) {
this.setStatus(ContractStatus.TESTED);
} else {
this.setStatus(ContractStatus.ERROR);
}
return this;
} catch (error) {
throw error;
}
}
/**
* @function getABI
* @memberof TestScilla
* @description get ABI from scilla runner
* @param {Object} params
* @param {String} params.code - code string
* @return {Object} RPC result
*/
async getABI({
code
}) {
// the endpoint for sendServer has been set to scillaProvider
try {
const result = await this.messenger.sendServer('/contract/check', {
code
});
if (result.result && result.message !== undefined) {
return JSON.parse(result.message);
}
} catch (error) {
throw error;
}
}
/**
* @function decodeABI
* @description decode ABI from scilla runner
* @param {Object} paramObject
* @param {String} paramObject.code - scilla code string
* @return {TestScilla} test contract
*/
async decodeABI({
code
}) {
try {
this.setCode(code);
const abiObj = await this.getABI({
code
});
this.setABI(abiObj);
return this;
} catch (error) {
throw error;
}
}
/**
* @function setBlockNumber
* @memberof TestScilla
* @description set block number for TestScilla
* @param {Number} number - block number setted to blockchain
* @return {TestScilla|false} test contract
*/
async setBlockNumber(number) {
try {
if (number && laksaUtils.isInt(Number(number))) {
this.setBlockchain(String(number));
this.setCreationBlock(String(number));
return this;
} else if (number === undefined) {
const result = await this.messenger.send('GetLatestTxBlock');
if (result) {
this.setBlockchain(result.header.BlockNum);
this.setCreationBlock(result.header.BlockNum);
return this;
}
}
} catch (error) {
throw error;
}
}
/**
* @function testPayload
* @memberof TestScilla.prototype
* @description construct payload for TestScilla
* @return {Object} payload object
*/
get testPayload() {
return _objectSpread({}, this.payload(), {
code: this.code,
data: JSON.stringify(this.init.concat(this.blockchain)).replace(/\\"/g, '"')
});
}
/**
* @function setABI
* @memberof TestScilla
* @description set abi for TestScilla
* @return {TestScilla} TestScilla instance
*/
setABI(abi) {
this.abi = new ABI(abi) || {};
return this;
}
/**
* @function setCode
* @memberof TestScilla
* @description set code for TestScilla
* @return {TestScilla} test contract
*/
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
*/
setInitParamsValues(initParams, arrayOfValues) {
const 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
*/
setCreationBlock(blockNumber) {
const result = setParamValues([{
vname: '_creation_block',
type: 'BNum'
}], [{
vname: '_creation_block',
type: 'BNum',
value: new laksaUtils.BN(blockNumber).toString()
}]);
const [...arr] = this.init;
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
*/
setBlockchain(blockNumber) {
const result = setParamValues([{
vname: 'BLOCKNUMBER',
type: 'BNum'
}], [{
vname: 'BLOCKNUMBER',
type: 'BNum',
value: new laksaUtils.BN(blockNumber).toString()
}]);
const [...arr] = this.blockchain;
arr.push(result[0]);
this.blockchain = arr;
return this;
}
}, (_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
*/
let Contracts = (_dec$2 = laksaShared.assertObject({
ContractAddress: ['isAddress', 'optional'],
code: ['isString', 'optional'],
init: ['isArray', 'optional'],
status: ['isString', 'optional']
}), (_class$2 = class Contracts extends laksaShared.Core {
constructor(messenger, signer) {
super();
/**
* @var {Messeger} messenger
* @memberof Contracts.prototype
* @description Messenger instance
*/
this.messenger = messenger;
/**
* @var {Wallet} signer
* @memberof Contracts.prototype
* @description Wallet instance
*/
this.signer = signer;
}
/**
* @function getAddressForContract
* @memberof Contracts
* @description get Contract address from Transaction
* @param {Transaction} tx - Transaction instance
* @return {String} Contract address
*/
getAddressForContract(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
*/
new(code, init) {
const newContract = new Contract({
code,
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
*/
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
*/
async testContract(code, init) {
const contract = new TestScilla({
code,
init
}, {
messenger: this.messenger,
signer: this.signer
}, ContractStatus.INITIALISED);
const result = await contract // decode ABI from code first
.decodeABI({
code
}) // we set the init params to decoded ABI
.then(decoded => decoded.setInitParamsValues(decoded.abi.getInitParams(), init)) // we get the current block number from node, and set it to params
.then(inited => inited.setBlockNumber()) // but we have to give it a test
.then(ready => ready.testCall(2000)) // now we change the status to wait for sign
.then(state => {
return state.status === ContractStatus.TESTED ? {
abi: state.abi,
init: state.init,
status: state.status
} : false;
});
return result;
}
}, (_applyDecoratedDescriptor(_class$2.prototype, "at", [_dec$2], Object.getOwnPropertyDescriptor(_class$2.prototype, "at"), _class$2.prototype)), _class$2));
exports.isInt = laksaUtils.isInt;
exports.isHash = laksaUtils.isHash;
exports.Matchers = Matchers;
exports.validators = validators;
exports.validate = validate;
exports.transform = transform;
exports.ABI = ABI;
exports.Contracts = Contracts;
exports.Contract = Contract;
exports.TestScilla = TestScilla;
exports.ContractStatus = ContractStatus;
exports.setParamValues = setParamValues;
exports.getAddressForContract = getAddressForContract;
Object.defineProperty(exports, '__esModule', { value: true });
})));