UNPKG

@swtc/serializer

Version:
322 lines 13 kB
"use strict"; // Represent amounts and currencies objects // in Jingtum. // - Numbers in hex are big-endian. var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.Factory = void 0; const bignumber_js_1 = __importDefault(require("bignumber.js")); const bn_plus_js_1 = __importDefault(require("bn-plus.js")); const extend_1 = __importDefault(require("extend")); const wallet_1 = require("@swtc/wallet"); const Utils_1 = require("./Utils"); const common_1 = require("@swtc/common"); // // Amount class in the style of Java's BigInteger class // https://docs.oracle.com/javase/7/docs/api/java/math/BigInteger.html // const Factory = (Wallet = (0, wallet_1.Factory)("jingtum")) => { var _a; const isAmount = (obj) => { if (obj === null || typeof obj !== "object" || typeof obj.value !== "string" || !(0, common_1.isFloat)(obj.value) || !(0, common_1.isTumCode)(obj.currency)) { return false; } if (obj.issuer) { if (!Wallet.isValidAddress(obj.issuer)) { return false; } } else { if (obj.currency !== Wallet.getCurrency()) { return false; } obj.issuer = ""; } return true; }; const isBalance = (obj) => { if (obj === null || typeof obj !== "object" || !(0, common_1.isFloat)(obj.freezed) || !(0, common_1.isFloat)(obj.value) || !(0, common_1.isTumCode)(obj.currency)) { return false; } if (!Wallet.isValidAddress(obj.counterparty)) { return false; } return true; }; const DataCheck = { allNumeric: common_1.allNumeric, isCustomTum: common_1.isCustomTum, isRelation: common_1.isRelation, isTumCode: common_1.isTumCode, isCurrency: common_1.isCurrency, isLetterNumer: common_1.isLetterNumer, isAmount, isBalance }; return _a = class Amount { static from_json(j) { return new _a().parse_json(j); } constructor() { // Json format: // integer : SWT // { 'value' : ..., 'currency' : ..., 'issuer' : ...} this._value = new bn_plus_js_1.default(0); // NaN for bad value. Always positive. this._offset = 0; // Always 0 for SWT. this._is_native = true; // Default to SWT. Only valid if value is not NaN. this._is_negative = false; this._currency = null; // new String; this._issuer = null; // new String; // Add constants to Amount class (0, extend_1.default)(this, common_1.AMOUNT_CONSTS); } is_valid() { if (this.is_native()) { return (0, Utils_1.isNumber)(this._value); } return isAmount({ value: this._value.toString(), currency: this._currency, issuer: this._issuer }); } currency() { return this._currency; } is_native() { return this._is_native; } offset() { return this._offset; } is_negative() { return this._is_negative; } is_positive() { return !this.is_zero() && !this.is_negative(); } is_zero() { return this._value.isZero(); } issuer() { return this._issuer; } /** * Only set the issuer if the input is a valid address. * * @param {string} issuer * @returns {Amount} * @memberof Amount */ parse_issuer(issuer) { if (Wallet.isValidAddress(issuer)) { this._issuer = issuer; } return this; } /** * For SWT, only keep as the integer with precision * * @param {string} j * @returns {Amount} * @memberof Amount */ parse_swt_value(j) { let m; if (typeof j === "string") { m = j.match(/^(-?)(\d*)(\.\d{0,6})?$/); } if (m) { if (m[3] === undefined) { // Integer notation // Changed to agree with floating, values multiplied by 1,000,000. this._value = new bignumber_js_1.default(m[2]).multipliedBy(1e6).toNumber(); // new BigInteger(m[2]); } else { // Float notation : values multiplied by 1,000,000. // only keep 6 digits after the decimal point. this._value = new bignumber_js_1.default(m[2] + m[3]).multipliedBy(1e6).toNumber(); // int_part+fraction_part;//int_part.add(fraction_part); } this._is_native = true; this._offset = 0; this._is_negative = Boolean(m[1]) && this._value !== 0; if (this._value > this.bi_xns_max) { this._value = NaN; } } else { this._value = NaN; } return this; } /** * Parse a non-native Tum value for the json wire format. * Requires _currency not as SWT! * * @param {(number | string)} j * @returns {Amount} * @memberof Amount */ parse_tum_value(j) { this._is_native = false; switch (typeof j) { case "number": this._is_negative = j < 0; this._value = new bn_plus_js_1.default(Math.abs(j)); this._offset = 0; break; case "string": const i = j.match(/^(-?)(\d+)$/); const d = !i && j.match(/^(-?)(\d*)\.(\d*)$/); const e = !d && j.match(/^(-?)(\d*)e(-?\d+)$/); // ? !e if (e) { // e notation this._value = e[2]; // new BigInteger(e[2]); this._offset = parseInt(e[3], 10); this._is_negative = Boolean(e[1]); } else if (d) { // float notation const precision = d[3].length; this._value = this._offset = -precision; // integer.multiply(Amount.bi_10.clone().pow(precision)).add(fraction); this._is_negative = Boolean(d[1]); } else if (i) { // integer notation this._value = i[2]; // new BigInteger(i[2]); this._offset = 0; this._is_negative = Boolean(i[1]); } else { this._value = NaN; } break; default: this._value = NaN; } return this; } /** * Convert the internal obj to JSON * * @returns {IAmount} * @memberof Amount */ to_json() { let result; if (this._is_native) { result = new bignumber_js_1.default(this._value.toString(10)) .dividedBy(1e6) .toString(10); } else { result = {}; result.value = new bignumber_js_1.default(this._value.toString(10)) .dividedBy(Math.pow(10, Math.abs(this._offset))) .toString(10); result.currency = this.currency(); if (this.is_valid()) { result.issuer = this._issuer; } } return result; } /** * Convert the internal Tum Code to byte array for serialization. * Input: a string represents the Tum. * Output: Bytes array of size 20 (UINT160). * * @returns {number[]} * @memberof Amount */ tum_to_bytes() { let currencyData = new Array(20).fill(0); // Only handle the currency with correct symbol if ((0, common_1.isCurrency)(this._currency)) { const currencyCode = this._currency; // 区分大小写 const end = 14; const len = currencyCode.length - 1; for (let j = len; j >= 0; j--) { currencyData[end - j] = currencyCode.charCodeAt(len - j) & 0xff; } } else if ((0, common_1.isCustomTum)(this._currency)) { // for TUM code start with 8 // should be HEX code currencyData = new bn_plus_js_1.default(this._currency, 16).toArray(undefined, 20); } else { throw new Error("Incorrect currency code length."); } return currencyData; } /** * Convert the input JSON data into a valid Amount object * Amount should have 3 properties: value、issuer/counterparty & currency * * Amount: * * number: 123456 * * string: "123456" * * obj: {"value": 129757.754575, "issuer":"", "currency":"USD"} * * @param {(number | string | IAmount)} in_json * @returns {Amount} * @memberof Amount */ parse_json(in_json) { if (typeof in_json === "number" || typeof in_json === "string") { this.parse_swt_value(in_json.toString()); } else if (in_json !== null && typeof in_json === "object") { if (!(0, common_1.isTumCode)(in_json.currency)) { throw new Error("Amount.parse_json: Input JSON has invalid Tum info!"); } // AMOUNT could have a field named either as 'issuer' or as 'counterparty' for SWT, this can be undefined if (in_json.currency !== Wallet.getCurrency()) { this._currency = in_json.currency; this._is_native = false; if (in_json.issuer && Wallet.isValidAddress(in_json.issuer)) { this._issuer = in_json.issuer; // TODO, need to find a better way for extracting the exponent and digits const vpow = Number(in_json.value).toExponential().toString(); const len = Number(vpow.substr(vpow.lastIndexOf("e") + 1)); const offset = 15 - len; const factor = Math.pow(10, offset); const newvalue = new bignumber_js_1.default(in_json.value) .multipliedBy(factor) .toString(); this._value = new bn_plus_js_1.default(newvalue, 10); this._offset = -1 * offset; } else { throw new Error("Amount.parse_json: Input JSON has invalid issuer info!"); } } else { this.parse_swt_value(in_json.value.toString()); } } else { throw new Error("Amount.parse_json: Unsupported JSON type!"); } return this; } }, _a.DataCheck = DataCheck, _a; }; exports.Factory = Factory; //# sourceMappingURL=TumAmount.js.map