@eversurf/dengine-js
Version:
Debot engine for Java Script
325 lines • 12.6 kB
JavaScript
;
/*
* Copyright 2018-2020 TON Labs LTD.
*
* Licensed under the SOFTWARE EVALUATION License (the "License"); you may not use
* this file except in compliance with the License.
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific TON DEV software governing permissions and
* limitations under the License.
*
*/
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.DebotClient = void 0;
const modules_1 = require("./modules");
const bin_1 = require("./bin");
const version_1 = require("./version");
class DebotClient {
constructor(config) {
this.context = undefined;
this.contextCreation = undefined;
this.contextError = undefined;
this.config = config !== null && config !== void 0 ? config : {};
this.client = new modules_1.ClientModule(this);
this.debot = new modules_1.DebotModule(this);
}
static set default(client) {
this._default = client;
}
static get default() {
if (this._default === null) {
this._default = new DebotClient(this._defaultConfig);
}
return this._default;
}
static set defaultConfig(config) {
this._defaultConfig = config;
}
static get defaultConfig() {
return this._defaultConfig;
}
static useBinaryLibrary(loader) {
(0, bin_1.useLibrary)(loader);
}
static toKey(d) {
return toHex(d, 256);
}
static toHash64(d) {
return toHex(d, 64);
}
static toHash128(d) {
return toHex(d, 128);
}
static toHash256(d) {
return toHex(d, 256);
}
static toHash512(d) {
return toHex(d, 512);
}
static toHex(dec, bits = 0) {
return toHex(dec, bits);
}
close() {
const context = this.context;
if (context !== undefined) {
this.context = undefined;
(0, bin_1.getBridge)().destroyContext(context);
}
}
resolveError(functionName, params, err) {
var _a;
return __awaiter(this, void 0, void 0, function* () {
if (err.code !== 23 || !((_a = err.data) === null || _a === void 0 ? void 0 : _a.suggest_use_helper_for)) {
return err;
}
return this.resolveApiError((yield this.client.get_api_reference()).api, functionName, params, err);
});
}
resolveErrorSync(functionName, params, err) {
var _a;
if (err.code !== 23 || !((_a = err.data) === null || _a === void 0 ? void 0 : _a.suggest_use_helper_for)) {
return err;
}
return this.resolveApiError(this.client.get_api_reference_sync().api, functionName, params, err);
}
resolveApiError(api, functionName, params, err) {
var _a, _b;
if (err.code !== 23 || !((_a = err.data) === null || _a === void 0 ? void 0 : _a.suggest_use_helper_for)) {
return err;
}
try {
const [modName, funcName] = functionName.split(".");
const allTypesArray = api.modules.reduce((accumulator, element) => accumulator.concat(element.types), []);
const allTypesDict = {};
allTypesArray.forEach((element) => allTypesDict[element.name] = element);
const module = api.modules.find((x) => x.name === modName);
const func = module.functions.find((x) => x.name === funcName);
const param = func.params[1];
// If there is only context param (or AppObject second param), there is nothing to analyze
if (!param || param.generic_name == "AppObject") {
return err;
}
const paramTypeInfo = allTypesDict[param.ref_name];
walkParameters(paramTypeInfo, params, "");
function walkParameters(valueTypeInfo, value, path) {
switch (valueTypeInfo.type) {
case "Array":
if (Array.isArray(value)) {
value.forEach(v => walkParameters(valueTypeInfo.array_item, v, `${path}[i]`));
}
break;
case "Struct":
valueTypeInfo.struct_fields.forEach((sf) => walkParameters(sf, value[sf.name], path ? `${path}.${sf.name}` : sf.name));
break;
case "Optional":
if (value) {
walkParameters(valueTypeInfo.optional_inner, value, path);
}
break;
case "Ref":
if (valueTypeInfo.ref_name != "Value" &&
valueTypeInfo.ref_name != "API" &&
valueTypeInfo.ref_name != "AbiParam") {
walkParameters(allTypesDict[valueTypeInfo.ref_name], value, path);
}
break;
case "EnumOfTypes":
if (valueTypeInfo.enum_types.some((et) => et.name == value.type)) {
return;
}
let parameterName = valueTypeInfo.name.toLowerCase();
let helperFunctions = [];
valueTypeInfo.enum_types.forEach((et) => helperFunctions.push(parameterName + et.name));
err.message = `Consider using one of the helper methods (${helperFunctions.join(", ")}) for the \"${path}\" parameter\n` + err.message;
break;
default:
break;
}
}
}
catch (e) {
err.message = (_b = e.message) !== null && _b !== void 0 ? _b : `${e}`;
}
return err;
}
getClientConfig(libName) {
return Object.assign(Object.assign({}, this.config), { binding: {
library: `dengine-js (${libName})`,
version: version_1.packageVersion,
} });
}
contextRequiredSync() {
if (this.context !== undefined) {
return this.context;
}
const bridge = (0, bin_1.getBridge)();
this.context = bridge.createContextSync(this.getClientConfig(bridge.getLibNameSync()));
return this.context;
}
contextRequired() {
if (this.context !== undefined) {
return Promise.resolve(this.context);
}
if (this.contextError !== undefined) {
return Promise.reject(this.contextError);
}
if (this.contextCreation === undefined) {
this.contextCreation = [];
const bridge = (0, bin_1.getBridge)();
(() => __awaiter(this, void 0, void 0, function* () {
try {
const config = this.getClientConfig(yield bridge.getLibName());
const context = yield bridge.createContext(config);
const creation = this.contextCreation;
this.contextCreation = undefined;
this.context = context;
creation === null || creation === void 0 ? void 0 : creation.forEach(x => x.resolve(context));
}
catch (err) {
const creation = this.contextCreation;
this.contextCreation = undefined;
this.contextError = err !== null && err !== void 0 ? err : undefined;
creation === null || creation === void 0 ? void 0 : creation.forEach(x => x.reject(err));
}
}))();
}
return new Promise((resolve, reject) => {
var _a;
(_a = this.contextCreation) === null || _a === void 0 ? void 0 : _a.push({
resolve,
reject,
});
});
}
request(functionName, functionParams, responseHandler) {
var _a;
return __awaiter(this, void 0, void 0, function* () {
const context = (_a = this.context) !== null && _a !== void 0 ? _a : yield this.contextRequired();
return (0, bin_1.getBridge)()
.request(context, functionName, functionParams, responseHandler !== null && responseHandler !== void 0 ? responseHandler : (() => {
}))
.catch((reason) => __awaiter(this, void 0, void 0, function* () {
throw yield this.resolveError(functionName, functionParams, reason);
}));
});
}
requestSync(functionName, functionParams) {
var _a;
const context = (_a = this.context) !== null && _a !== void 0 ? _a : this.contextRequiredSync();
const bridge = (0, bin_1.getBridge)();
try {
return bridge.requestSync(context, functionName, functionParams);
}
catch (err) {
throw this.resolveErrorSync(functionName, functionParams, err);
}
}
resolve_app_request(app_request_id, result) {
return __awaiter(this, void 0, void 0, function* () {
if (app_request_id) {
yield this.client.resolve_app_request({
app_request_id,
result: {
type: "Ok",
result,
},
});
}
});
}
reject_app_request(app_request_id, error) {
return __awaiter(this, void 0, void 0, function* () {
if (app_request_id) {
yield this.client.resolve_app_request({
app_request_id,
result: {
type: "Error",
text: error.message,
},
});
}
});
}
}
exports.DebotClient = DebotClient;
DebotClient._defaultConfig = {};
DebotClient._default = null;
// Converts value to hex
function toHex(value, bits) {
let hex;
if (typeof value === "number" || typeof value === "bigint") {
hex = value.toString(16);
}
else if (typeof value === "string") {
if (value.startsWith("0x")) {
hex = value.substring(2);
}
else {
hex = decToHex(value);
}
}
else {
hex = value.toString();
}
let len = bits / 4;
while (hex.length > len && hex.startsWith("0")) {
hex = hex.substring(1);
}
return hex.padStart(len, "0");
}
function decToHex(dec) {
var _a;
let bigNum = [];
for (let i = 0; i < dec.length; i += 1) {
const d = ((_a = dec.codePointAt(i)) !== null && _a !== void 0 ? _a : 0) - 48;
const mul8 = shl(bigNum, 3);
const mul2 = shl(bigNum, 1);
const mul10 = add(mul8, mul2);
bigNum = add(mul10, [d]);
}
let hex = "";
for (let i = bigNum.length - 1; i >= 0; i -= 1) {
hex += bigNum[i].toString(16).padStart(4, "0");
}
return hex;
}
function shl(bigNum, bits) {
let rest = 0;
const result = [];
for (let i = 0; i < bigNum.length; i += 1) {
let v = (bigNum[i] << bits) + rest;
result.push(v & 0xFFFF);
rest = (v >> 16) & 0xFFFF;
}
if (rest > 0) {
result.push(rest);
}
return result;
}
function add(a, b) {
let rest = 0;
const result = [];
const len = Math.max(a.length, b.length);
for (let i = 0; i < len; i += 1) {
let v = (i < a.length ? a[i] : 0) + (i < b.length ? b[i] : 0) + rest;
result.push(v & 0xFFFF);
rest = (v >> 16) & 0xFFFF;
}
if (rest > 0) {
result.push(rest);
}
return result;
}
//# sourceMappingURL=client.js.map