eosplayer
Version:
eosplayer is the glue layer of eosjs, which is packaged based on eosjs and provides better usability for the application layer. It can be used on browsers already installed scatter or in Dapp wallets.
1,018 lines • 50.4 kB
JavaScript
'use strict';
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
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) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __generator = (this && this.__generator) || function (thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (_) try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
};
Object.defineProperty(exports, "__esModule", { value: true });
var axios_1 = require("axios");
var bignumber_js_1 = require("bignumber.js");
var wait_1 = require("../utils/wait");
var log_1 = require("../utils/log");
var libs_1 = require("../types/libs");
var cQueue_1 = require("../utils/cQueue");
var DEFAULT_FETCH_TIMEOUT = 60000;
var log = log_1.createLogger('chain');
var storyBoard = new cQueue_1.CQueue(1000, true);
/**
* chain helper, supported chain operations
* @author kinghand@foxmail.com
*/
var ChainHelper = /** @class */ (function () {
function ChainHelper(_eos) {
this._eos = _eos;
}
Object.defineProperty(ChainHelper.prototype, "storyBoard", {
get: function () {
return storyBoard;
},
enumerable: true,
configurable: true
});
/**
* get info of the chain connected
* @return {Promise<*>}
*/
ChainHelper.prototype.getInfo = function () {
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, this._eos.getInfo({})];
case 1: return [2 /*return*/, (_a.sent())];
}
});
});
};
/**
* get specific block of the chain
* @param blockNumOrId
* @return {Promise<*>}
*/
ChainHelper.prototype.getBlock = function (blockNumOrId) {
return __awaiter(this, void 0, void 0, function () {
var params;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
params = {
block_num_or_id: blockNumOrId,
};
return [4 /*yield*/, this._eos.getBlock(params)];
case 1: return [2 /*return*/, (_a.sent())];
}
});
});
};
/**
* get contract
* @param code
* @return {Promise<void>}
*/
ChainHelper.prototype.getContract = function (code) {
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, this._eos.contract(code)];
case 1: return [2 /*return*/, _a.sent()];
}
});
});
};
/**
* get the abi of contract
* @param code
* @return {Promise<*>}
*/
ChainHelper.prototype.getAbi = function (code) {
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, this._eos.getAbi(code)];
case 1: return [2 /*return*/, _a.sent()];
}
});
});
};
/**
* get the definition of a table in specific contract abi
* @param code
* @param tableName
* @return {Promise<*|undefined>}
*/
ChainHelper.prototype.getTableAbi = function (code, tableName) {
return __awaiter(this, void 0, void 0, function () {
var abi;
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, this.getAbi(code)];
case 1:
abi = _a.sent();
return [2 /*return*/, abi.abi.tables.find(function (desc) { return desc.name === tableName; })];
}
});
});
};
/**
* abiJsonToBin
* @param code
* @param action
* @param args
* @return {Promise<string>}
*/
ChainHelper.prototype.abiJsonToBin = function (code, action, args) {
return __awaiter(this, void 0, void 0, function () {
var params;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
params = {
code: code,
action: action,
args: args,
};
return [4 /*yield*/, this._eos.abiJsonToBin(params)];
case 1: return [2 /*return*/, (_a.sent()).binargs];
}
});
});
};
/**
* get account info of any user
* @param {string|number} account_name - string name or id
* @return {Promise<{AccountInfo}>}
*/
ChainHelper.prototype.getAccountInfo = function (account_name) {
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, this._eos.getAccount({ account_name: account_name })];
case 1: return [2 /*return*/, _a.sent()];
}
});
});
};
/**
* get first public key of an account
* @param account_name - account_name
* @param authority - default is 'active'
* @return {Promise<*>}
* @constructor
*/
ChainHelper.prototype.getPubKey = function (account_name, authority) {
if (authority === void 0) { authority = 'active'; }
return __awaiter(this, void 0, void 0, function () {
var pubkeys;
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, this.getPubKeys(account_name, authority)];
case 1:
pubkeys = (_a.sent());
if (!pubkeys || pubkeys.length <= 0) {
log.warning("cannot find public key for " + account_name + "@" + authority);
return [2 /*return*/];
}
return [4 /*yield*/, this.getPubKeys(account_name, authority)];
case 2: return [2 /*return*/, (_a.sent())[0].key];
}
});
});
};
/**
* get public keys of an account
* @param account_name
* @param authority - default is 'active'
* @return {Promise<*>}
* @constructor
*/
ChainHelper.prototype.getPubKeys = function (account_name, authority) {
if (authority === void 0) { authority = 'active'; }
return __awaiter(this, void 0, void 0, function () {
var accountInfo, permission;
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, this.getAccountInfo(account_name)];
case 1:
accountInfo = _a.sent();
permission = accountInfo.permissions.find(function (v) { return v.perm_name === authority; });
if (!permission)
throw new Error("cannot find the permission of " + account_name);
return [2 /*return*/, permission.required_auth.keys];
}
});
});
};
/**
* recover public key from signature
* @param signature - signed data
* @param message
* @return {string}
*/
ChainHelper.prototype.recoverSign = function (signature, message) {
return libs_1.Ecc.recover(signature, message);
};
/**
* validate if signed data is signed by a account
* @param signature - signed data
* @param message
* @param account_name
* @param authority - default is 'active'
* @param {Array.<ISignPlugin>} signPlugins - plugins for validate sign
* @example
* validateSign(SIG, MSG, ACC, 'active', { ['pretonarts11@eosio.code'] : async (account, recoverKey) => validate rpc ... }
* @return {string|undefined} - recover public key, and it's failed when 'undefined' return.
*/
ChainHelper.prototype.validateSign = function (signature, message, account_name, authority) {
if (authority === void 0) { authority = 'active'; }
var signPlugins = [];
for (var _i = 4; _i < arguments.length; _i++) {
signPlugins[_i - 4] = arguments[_i];
}
return __awaiter(this, void 0, void 0, function () {
var recoverKey, permissions, perm, _a, accounts, keys, keyObj, accStrs, iPlg, signPlugin, i, account, validator, _b;
return __generator(this, function (_c) {
switch (_c.label) {
case 0:
recoverKey = this.recoverSign(signature, message);
return [4 /*yield*/, this.getAccountInfo(account_name)];
case 1:
permissions = (_c.sent()).permissions;
if (!permissions) {
log.warning("permissions of account_name " + account_name + " are not found.");
return [2 /*return*/];
}
perm = permissions.find(function (p) { return p.perm_name === authority; });
if (!permissions) {
log.warning("permission " + authority + " account_name " + account_name + " are not found.");
return [2 /*return*/];
}
_a = perm.required_auth, accounts = _a.accounts, keys = _a.keys;
keyObj = keys.find(function (v) { return v.key === recoverKey; });
if (keyObj) {
return [2 /*return*/, keyObj.key];
}
if (!signPlugins || signPlugins.length <= 0) {
return [2 /*return*/];
}
accStrs = accounts.map(function (acc) { return acc.permission.actor + "@" + acc.permission.permission; });
log.verbose('try match', accounts, accStrs, signPlugins);
iPlg = 0;
_c.label = 2;
case 2:
if (!(iPlg < signPlugins.length)) return [3 /*break*/, 8];
signPlugin = signPlugins[iPlg];
i = 0;
_c.label = 3;
case 3:
if (!(i < accStrs.length)) return [3 /*break*/, 7];
account = accStrs[i];
validator = signPlugin.validatorProvider[account];
_b = validator;
if (!_b) return [3 /*break*/, 5];
return [4 /*yield*/, Promise.resolve(validator(account_name, recoverKey, this))];
case 4:
_b = (_c.sent());
_c.label = 5;
case 5:
if (_b) {
return [2 /*return*/, recoverKey];
}
_c.label = 6;
case 6:
i++;
return [3 /*break*/, 3];
case 7:
iPlg++;
return [3 /*break*/, 2];
case 8: return [2 /*return*/];
}
});
});
};
/**
* get a account's action count
* @param {string|number} account_name - string name or id
* @return {Promise<number>}
*/
ChainHelper.prototype.getActionCount = function (account_name) {
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, this.getActionMaxSeq(account_name)];
case 1: return [2 /*return*/, (_a.sent()) + 1];
}
});
});
};
/**
* get a account's max seq
* @param {string|number} account_name - string name or id
* @return {Promise<number>} - return -1 if there is no action
*/
ChainHelper.prototype.getActionMaxSeq = function (account_name) {
return __awaiter(this, void 0, void 0, function () {
var recentActions, acts;
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, this.getRecentActions(account_name)];
case 1:
recentActions = _a.sent();
if (!recentActions || !recentActions.actions) {
throw new Error("getActionCount failed: cannot find recent actions of " + account_name + ")");
}
acts = recentActions.actions;
return [2 /*return*/, acts.length === 0 ? -1 : acts[acts.length - 1].account_action_seq];
}
});
});
};
/**
* get recent actions
* @param account_name
* @return {Promise<Array>}
*/
ChainHelper.prototype.getRecentActions = function (account_name) {
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, this._eos.getActions({ account_name: account_name })];
case 1: return [2 /*return*/, _a.sent()];
}
});
});
};
/**
* get actions of an account
* @desc to avoid searching in huge amount actions, the application layer should check the getActionCount before calling thi method
* @param {string|number} account_name - string name or id
* @param {number} startPos - start from 0
* @param {number} offset - when offset is 0, one object returned, offset ==(should be) count - 1
* @param {number} fetchTimeout - fetch time out (ms)
* @return {Promise<Array>} - [startPos, ..., startPos + offset]
*/
ChainHelper.prototype.getActions = function (account_name, startPos, offset, fetchTimeout) {
if (startPos === void 0) { startPos = 0; }
if (offset === void 0) { offset = 0; }
if (fetchTimeout === void 0) { fetchTimeout = DEFAULT_FETCH_TIMEOUT; }
return __awaiter(this, void 0, void 0, function () {
var pos, endPos, actions, ret, ex_1, acts, maxActionInd;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
pos = startPos;
endPos = startPos + offset;
actions = [];
log.verbose('getActions start', startPos, endPos, 'current:', actions.length);
_a.label = 1;
case 1:
if (!true) return [3 /*break*/, 6];
ret = void 0;
_a.label = 2;
case 2:
_a.trys.push([2, 4, , 5]);
return [4 /*yield*/, wait_1.timeoutPromise(fetchTimeout, this._eos.getActions({ account_name: account_name, pos: pos, offset: endPos - pos }))];
case 3:
ret = _a.sent();
return [3 /*break*/, 5];
case 4:
ex_1 = _a.sent();
log.warning(ex_1);
return [3 /*break*/, 1];
case 5:
if (!ret || !ret.actions) {
throw new Error("getActions failed: cannot find actions of " + account_name + " (pos:" + pos + ", offset:" + offset + ")");
}
acts = ret.actions;
log.verbose('getActions find', acts[acts.length - 1]);
maxActionInd = acts.length === 0 ? pos - 1 : acts[acts.length - 1].account_action_seq;
if (maxActionInd < pos) {
return [3 /*break*/, 6];
}
actions.push.apply(actions, acts);
if (maxActionInd >= endPos) {
return [3 /*break*/, 6];
}
pos = maxActionInd + 1;
return [3 /*break*/, 1];
case 6: return [2 /*return*/, actions];
}
});
});
};
/**
* Get all the actions in bulk
* @param account_name
* @param cbReceive - using this callback to receive list of actions
* @param startPos
* @param count
* @param concurrent
* @return {Promise<void>}
*/
ChainHelper.prototype.getAllActionsBatch = function (account_name, cbReceive, startPos, count, concurrent) {
if (startPos === void 0) { startPos = 0; }
if (count === void 0) { count = 100; }
if (concurrent === void 0) { concurrent = 10; }
return __awaiter(this, void 0, void 0, function () {
var offset, req, ranges, tStart, i, tRound, results, nonEmptyResults, allFull;
var _this = this;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
offset = count - 1;
if (!cbReceive) {
return [2 /*return*/, false];
}
req = function (pos) { return __awaiter(_this, void 0, void 0, function () {
var ex_2;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
if (!true) return [3 /*break*/, 5];
_a.label = 1;
case 1:
_a.trys.push([1, 3, , 4]);
log.verbose("search Start : at:" + Date.now() + " pos:" + pos + " offset:" + offset);
return [4 /*yield*/, this.getActions(account_name, pos, offset)];
case 2: return [2 /*return*/, _a.sent()];
case 3:
ex_2 = _a.sent();
log.error('error : ', ex_2);
return [3 /*break*/, 4];
case 4: return [3 /*break*/, 0];
case 5: return [2 /*return*/];
}
});
}); };
ranges = [];
log.info("===> start search actions of " + account_name + " from " + startPos + ", concurrent : " + concurrent + ", count : " + count + ", once : " + concurrent * count);
tStart = Date.now();
i = 0;
_a.label = 1;
case 1:
ranges.push(startPos + i * count);
if (!(i % concurrent === 0)) return [3 /*break*/, 3];
tRound = Date.now();
log.verbose("===> deal batch " + i + " : " + ranges + " at " + tStart);
return [4 /*yield*/, Promise.all(ranges.map(req))];
case 2:
results = _a.sent();
nonEmptyResults = results.filter(function (acts) { return acts.length > 0; });
if (nonEmptyResults.length <= 0) {
return [3 /*break*/, 4];
}
log.verbose("===> deal batch " + i + " done (" + (Date.now() - tRound) + ")");
allFull = results
.filter(function (acts) { return acts.length > 0; })
.reduce(function (full, acts) {
if (full) {
cbReceive(acts);
}
return full && acts.length >= count; // end when not full
}, true);
log.verbose("===> send batch " + i + " done (" + (Date.now() - tRound) + ")");
if (!allFull) {
return [3 /*break*/, 4];
}
ranges = [];
_a.label = 3;
case 3:
i++;
return [3 /*break*/, 1];
case 4:
log.info("getAllActions : all scaned (" + (Date.now() - tStart) + ")");
// return ret;
return [2 /*return*/, true];
}
});
});
};
/**
* get balance of specific account
* @param account_name - user's account name
* @param code - Account of the currency contract. The default code is "eosio.token", which is the currency code of eos
* @param symbolName - the token's symbol name
* @return {Promise<string|undefined>} asset format '1.0000 EOS'
*/
ChainHelper.prototype.getBalance = function (account_name, code, symbolName) {
if (code === void 0) { code = 'eosio.token'; }
return __awaiter(this, void 0, void 0, function () {
var balances;
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, this.getBalances(account_name, code)];
case 1:
balances = _a.sent();
if (!symbolName) {
log.warning('Symbol of the token has not been specified, the first item will return. all:', balances);
return [2 /*return*/, balances[0] || null];
}
else {
return [2 /*return*/, balances.find(function (v) { return v.endsWith(symbolName); }) || null];
}
return [2 /*return*/];
}
});
});
};
/**
* get balance of specific account
* @param account_name - user's account name
* @param code - Account of the currency contract. The default code is "eosio.token", which is the currency code of eos
* @return {Promise<Array>} - list of asset, asset format is like '1.0000 EOS'
*/
ChainHelper.prototype.getBalances = function (account_name, code) {
if (code === void 0) { code = 'eosio.token'; }
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, this._eos.getCurrencyBalance(code, account_name)];
case 1: return [2 /*return*/, ((_a.sent()) || []).map(function (v) { return v.trim(); })];
}
});
});
};
/**
* transfer
* @param {Object} account - {name, authority}
* @param {string} target - eos account, can be user or contract
* @param {string} quantity - eos asset format, e.p. "1.0000 EOS"
* @param {string} memo - memo
* @param {string} tokenAccount - name of token account - default is 'eosio.token'
* @param {Function} cbError - memo
* @return {Promise<Object>} transactionData
*/
ChainHelper.prototype.transfer = function (account, target, quantity, memo, cbError, tokenAccount) {
if (memo === void 0) { memo = ''; }
return __awaiter(this, void 0, void 0, function () {
var data, auth, trx, e_1;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
data = {
from: account.name,
to: target,
quantity: quantity,
memo: memo,
};
auth = {
actor: account.name,
permission: account.authority,
};
_a.label = 1;
case 1:
_a.trys.push([1, 3, , 4]);
return [4 /*yield*/, this.call(tokenAccount || 'eosio.token', 'transfer', data, auth).catch((cbError) || log.error)];
case 2:
trx = _a.sent();
return [3 /*break*/, 4];
case 3:
e_1 = _a.sent();
cbError(e_1);
return [3 /*break*/, 4];
case 4:
// const transOptions = {authorization: [`${account.name}@${account.authority}`]};
// const trx = await this._eos.transfer(account.name, target, quantity, memo, transOptions).catch(
// (cbError) || log.error,
// );
if (trx) {
log.info("Transfer dealed, txID: " + trx.transaction_id);
}
return [2 /*return*/, trx];
}
});
});
};
/**
* check a transaction info, retry once per sec until success
* @param {string} txID
* @param {number} maxRound
* @param {number} timeSpanMS
* @return {Promise<Object>} transaction
*/
ChainHelper.prototype.waitTx = function (txID, maxRound, timeSpanMS) {
if (maxRound === void 0) { maxRound = 12; }
if (timeSpanMS === void 0) { timeSpanMS = 1009; }
return __awaiter(this, void 0, void 0, function () {
var checkTx;
var _this = this;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
checkTx = function (_txID, round) {
if (round === void 0) { round = 0; }
return __awaiter(_this, void 0, void 0, function () {
var tx, err_1;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
_a.trys.push([0, 2, , 3]);
return [4 /*yield*/, this._eos.getTransaction(_txID)];
case 1:
tx = _a.sent();
if (tx)
return [2 /*return*/, tx];
return [3 /*break*/, 3];
case 2:
err_1 = _a.sent();
log.verbose("wait tx " + _txID + ", retry round: " + round + ". " + err_1.message);
return [3 /*break*/, 3];
case 3:
if (round >= maxRound) {
log.error("wait tx failed, round out.");
return [2 /*return*/, null];
}
return [4 /*yield*/, wait_1.forMs(timeSpanMS)];
case 4:
_a.sent();
return [2 /*return*/, checkTx(_txID, round + 1)];
}
});
});
};
return [4 /*yield*/, checkTx(txID)];
case 1: return [2 /*return*/, _a.sent()];
}
});
});
};
/**
* send action to a contract
* @param {string} code - account of contract
* @param {string} func - function name
* @param {*} jsonData - data
* @param {Array<IAuthorization>} authorization - should be an object who has keys {actor, permission}
* @return {Promise<*>} - transaction
*/
ChainHelper.prototype.call = function (code, func, jsonData) {
var authorization = [];
for (var _i = 3; _i < arguments.length; _i++) {
authorization[_i - 3] = arguments[_i];
}
return __awaiter(this, void 0, void 0, function () {
var data, trx;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
data = {
actions: [{
account: code,
name: func,
data: jsonData,
authorization: authorization,
}],
};
return [4 /*yield*/, this._eos.transaction(data).catch(function (e) {
throw e;
})];
case 1:
trx = _a.sent();
this.storyBoard.push(data);
log.info('CALL', 'code', code, 'func', func, 'jsonData', jsonData, 'authorization', authorization, 'history', this.storyBoard.toArray());
return [2 /*return*/, trx];
}
});
});
};
/**
* get all items in a table
* @desc this method can be very fast (infinitely close to once rpc time) when provide hint table
* @param {string} code - the contract
* @param {string} tableName - name of the table
* @param {string} scope
* @param {number} lowerNum - lower position, can be number or stringNumber, cannot be account_name
* @param {number} upperNum - lower position, can be number or stringNumber, cannot be account_name
* @param {Array<number>} hint - hint table to speed up search
* @example getTable("contract", "table", "scope", 0, -1, "4611686018427387903", "6917529027641081856", "9223372036854775808", "13835058055282163712")
* @return {Promise<Array>}
*/
ChainHelper.prototype.getTableAll = function (code, tableName, scope, lowerNum, upperNum) {
var hint = [];
for (var _i = 5; _i < arguments.length; _i++) {
hint[_i - 5] = arguments[_i];
}
return __awaiter(this, void 0, void 0, function () {
var lower, upper, ret, pool, Require;
var _this = this;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
lower = lowerNum ? new bignumber_js_1.BigNumber(lowerNum) : new bignumber_js_1.BigNumber(0);
upper = upperNum && upperNum !== -1 ? new bignumber_js_1.BigNumber(upperNum) : new bignumber_js_1.BigNumber('18446744073709551615');
ret = [];
pool = [];
Require = function (_l, _u) {
log.verbose('search ', Date.now(), _l.toFixed(0), _u.toFixed(0));
if (_l.gte(_u))
return;
var _promise = _this._eos.getTableRows({
json: true,
code: code,
scope: scope,
table: tableName,
limit: -1,
lower_bound: _l.toFixed(0),
upper_bound: _u.toFixed(0),
}).then(function (result) {
var _myInd = pool.findIndex(function (v) { return v === _promise; });
pool.splice(_myInd, 1);
if (!result) {
return;
}
if (!result.more) {
if (result.rows) {
ret.push.apply(ret, result.rows);
}
}
else {
var _mid = _u.minus(_l).dividedBy(2).decimalPlaces(0).plus(_l);
Require(_l, _mid.minus(1));
Require(_mid, _u);
}
}).catch(function (err) {
var _myInd = pool.find(function (v) { return v === _promise; });
pool.splice(_myInd, 1);
throw err;
});
pool.push(_promise);
};
if (!hint || hint.length <= 0) {
Require(lower, upper);
}
else {
hint.map(function (i) { return new bignumber_js_1.BigNumber(i); }).concat([upper]).reduce(function (_l, _m) {
Require(_l, _m);
return _m;
}, lower);
}
_a.label = 1;
case 1:
if (!(pool.length > 0)) return [3 /*break*/, 3];
return [4 /*yield*/, wait_1.forMs(50)];
case 2:
_a.sent();
return [3 /*break*/, 1];
case 3:
log.verbose('done search ', Date.now(), lower.toFixed(0), upper.toFixed(0));
return [2 /*return*/, ret];
}
});
});
};
/**
* check a table
* @desc the tag 'more' are not handled.
* @param {string} code - the contract
* @param {string} tableName - name of the table
* @param {string} scope
* @param {number} limit
* @param {number | string} lower_bound
* @param {number | string} upper_bound
* @param {number} index_position
* @return {Promise<Array>}
*/
ChainHelper.prototype.checkTable = function (code, tableName, scope, limit, lower_bound, upper_bound, index_position) {
if (limit === void 0) { limit = 10; }
if (lower_bound === void 0) { lower_bound = 0; }
if (upper_bound === void 0) { upper_bound = -1; }
if (index_position === void 0) { index_position = 1; }
return __awaiter(this, void 0, void 0, function () {
var result, ret;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
log.verbose('search ', Date.now(), lower_bound, upper_bound, limit);
return [4 /*yield*/, this._eos.getTableRows({
json: true,
code: code,
scope: scope,
table: tableName,
limit: limit,
lower_bound: lower_bound,
upper_bound: upper_bound,
index_position: index_position,
})];
case 1:
result = _a.sent();
ret = result && result.rows ? result.rows : [];
if (result.more && (limit <= 0 || (result.rows && result.rows.length < limit))) { // deal with 'more'
log.warning("'more' detected, and this method didn't deal with the tag 'more'. if you want to get all results, using checkTableMore and provide the primary key. ");
}
return [2 /*return*/, ret];
}
});
});
};
/**
* check a table
* @desc the tag 'more' are handled. it means that the result would not be truncated.
* @param {string} code - the contract
* @param {string} tableName - name of the table
* @param {string} scope
* @param {string} primaryKey - the key for indexing
* @param {number} limit
* @param {number | string} lower_bound
* @param {number | string} upper_bound
* @param {number} index_position
* @return {Promise<Array>}
*/
ChainHelper.prototype.checkTableMore = function (code, tableName, scope, primaryKey, limit, lower_bound, upper_bound, index_position) {
if (limit === void 0) { limit = 9999999; }
if (lower_bound === void 0) { lower_bound = 0; }
if (upper_bound === void 0) { upper_bound = -1; }
if (index_position === void 0) { index_position = 1; }
return __awaiter(this, void 0, void 0, function () {
var result, ret, from, to, abi, partResult;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
log.verbose('search ', code, tableName, Date.now());
return [4 /*yield*/, this._eos.getTableRows({
json: true,
code: code,
scope: scope,
table: tableName,
limit: limit,
lower_bound: lower_bound,
upper_bound: upper_bound,
index_position: index_position,
})];
case 1:
result = _a.sent();
ret = result && result.rows ? result.rows : [];
log.verbose("part size " + ret.length + ".");
if (!(result.more && (limit <= 0 || (result.rows && result.rows.length < limit)))) return [3 /*break*/, 5];
from = ret[0][primaryKey];
to = ret[ret.length - 1][primaryKey];
if (!(!from || !to)) return [3 /*break*/, 3];
return [4 /*yield*/, this.getAbi(code)];
case 2:
abi = _a.sent();
log.error("searching more error with primary key : " + primaryKey + ". please check\nlast data: " + ret[ret.length - 1] + " \nabi " + JSON.stringify(abi));
throw new Error("check more error with primary key : " + primaryKey);
case 3:
log.info("'more' detected: start searching results from " + to + ".");
return [4 /*yield*/, this.checkTableMore(code, tableName, scope, primaryKey, limit - ret.length + 1, to, upper_bound, index_position)];
case 4:
partResult = _a.sent();
return [2 /*return*/, ret.concat(partResult.splice(1))];
case 5: return [2 /*return*/, ret];
}
});
});
};
/**
* check range in table
* @desc the tag 'more' are handled. it means that the result would not be truncated.
* @param {string} code - the contract
* @param {string} tableName - name of the table
* @param {string} scope
* @param {number | string} from - start position or username
* @param {number} length
* @param {number} index_position
* @return {Promise<Array>}
*/
ChainHelper.prototype.checkTableRange = function (code, tableName, scope, from, length, index_position) {
if (length === void 0) { length = 1; }
if (index_position === void 0) { index_position = 1; }
return __awaiter(this, void 0, void 0, function () {
var rows;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
if (length < 0) {
throw new Error("range error: length(" + length + ") must larger than 0 ");
}
return [4 /*yield*/, this.checkTable(code, tableName, scope, length, from, (typeof from === 'number') ?
from + length :
new bignumber_js_1.BigNumber(libs_1.Eos.modules.format.encodeName(from, false)).plus(length).toString(), index_position)];
case 1:
rows = _a.sent();
return [2 /*return*/, rows];
}
});
});
};
/**
* check a item in a table
* @param {string} code - the contract
* @param {string} tableName
* @param {string} scope
* @param {number} key
* @return {Promise<*>}
*/
ChainHelper.prototype.checkTableItem = function (code, tableName, scope, key) {
return __awaiter(this, void 0, void 0, function () {
var rows;
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, this.checkTableRange(code, tableName, scope, key, 1)];
case 1:
rows = _a.sent();
return [2 /*return*/, rows[0]];
}
});
});
};
/**
* update auth
* @param account_name
* @param permission
* @param parent
* @param threshold
* @param keys
* @param accounts
* @param waits
* @returns {Promise<*>}
*/
ChainHelper.prototype.updateAuth = function (account_name, permission, parent, threshold, keys, accounts, waits) {
if (waits === void 0) { waits = 1; }
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, this._eos.updateauth({
account_name: account_name,
permission: permission,
parent: parent,
auth: {
threshold: threshold,
keys: keys,
accounts: accounts,
waits: waits,
},
})];
case 1: return [2 /*return*/, _a.sent()];
}
});
});
};
ChainHelper.getTableByScope = function (host, code, table, lower_bound, upper_bound, limit) {
if (limit === void 0) { limit = 1000; }
return __awaiter(this, void 0, void 0, function () {
var api, params, req, ret, rsp;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
api = '/v1/chain/get_table_by_scope';
params = {
code: code,
table: table,
lower_bound: lower_bound,
upper_bound: upper_bound,
limit: limit,
};
req = axios_1.default.create({
baseURL: host,
headers: {
post: {
'Content-Type': 'application/json',
},
},
});
ret = [];
_a.label = 1;
case 1:
if (!true) return [3 /*break*/, 3];
return [4 /*yield*/, req.post(api, params)];
case 2:
rsp = _a.sent();
ret.push(rsp.data);
if (rsp.data.more === '') {
return [3 /*break*/, 3];
}
return [3 /*break*/, 1];
case 3: return [2 /*return*/, ret];
}
});
});
};
ChainHelper.help = function () {
return "\n### Chain API\n\n```js\n{Object} async getInfo() // get info of the chain connected\n{Object} async getBlock(blockNumOrId) // get specific block of the chain\n\n\n{Contract} async getContract(code) // get contract\n{Object} async getAbi(code) // get abi of contract\n{Object} async getTableAbi(code, tableName) // get table abi of contract\n{Object} async abiJsonToBin(code, action, args)\n\n{Object} async getAccountInfo(account_name) // get account info of any user\n{string} async getPubKey(account_name, authority = \"active\") // get the first public key of an account\n{Array} async getPubKeys(account_name, authority = \"active\") // get public keys of an account\n{string} async recoverSign(signature, message) // recover sign and to the public key\n{string} async validateSign (signature, message, account, authority = 'active', accountsPermisionPlugins)\n// validate if signed data is signed by a account. it returns the matched public key\n\n{Number} async getActionCount(account_name) // get a account's action count\n{Number} async getActionMaxSeq(account_name) // get a account's max action seq\n{Array} async getRecentActions(account_name) // get recent actions\n{Array} async getActions(account_name, startPos = 0, offset = 0) // get all actions of an account\n{Array} async getAllActionsBatch (account_name, cbReceive, startPos = 0, count = 100, concurrent = 10) // get all actions in bulk\n\n{String} async getBalance(account_name, code = \"eosio.token\", symbolName = undefined) // get balance of specific account\n{Array.<String>} async getBalances(account_name, code = \"eosio.token\") // get all balance of specific account\n{Tx} async transfer(account, target, quantity, memo = \"\", cbError) // the format of account should be {name, authority}\n\n{Tx} async waitTx(txID, maxRound = 12, timeSpanMS = 1009) // check a transaction info, retry once per sec until success\n\n{Tx} async call(code, func, jsonData, ...authorization) // send action to a contract\n\n{Array} async getTableAll(code, tableName, scope, lowerNum, upperNum, ...hint) // get all items in a table\n{Array} async checkTable(code, tableName, scope, limit = 10, lower_bound = 0, upper_bound = -1, index_position = 1) // check a table\n{Array} async checkTableMore(code, tableName, scope, primaryKey, limit = 9999999, lower_bound = 0, upper_bound = -1, index_position = 1)\n{Array} async checkTableRange(code, tableName, scope, from,