UNPKG

@logosnetwork/logos-webwallet-sdk

Version:

Create Logos wallets with or without a full Logos node

1,067 lines (1,066 loc) 60.3 kB
"use strict"; var __extends = (this && this.__extends) || (function () { var extendStatics = function (d, b) { extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; return extendStatics(d, b); }; return function (d, b) { extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; })(); 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()); }); }; 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 }; } }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); var big_integer_1 = __importDefault(require("big-integer")); var Account_1 = __importDefault(require("./Account")); var Utils_1 = require("./Utils/Utils"); var Requests_1 = require("./Requests"); /** * TokenAccount contain the keys, chains, and balances. */ var TokenAccount = /** @class */ (function (_super) { __extends(TokenAccount, _super); // private _pendingTokenBalance: string // private _pendingTotalSupply: string function TokenAccount(options) { var _this = this; if (!options) throw new Error('You must pass settings to initalize the token account'); if (!options.address && !options.tokenID) throw new Error('You must initalize a token account with an address or tokenID'); if (!options.wallet) throw new Error('You must initalize a token account with a wallet'); if (options.tokenID !== undefined) { options.publicKey = options.tokenID; options.address = Utils_1.accountFromHexKey(options.tokenID); } else if (options.address !== undefined) { options.publicKey = Utils_1.keyFromAccount(options.address); } _this = _super.call(this, options) || this; if (options.issuance !== undefined && options.issuance !== null) { _this._tokenBalance = options.issuance.totalSupply; _this._totalSupply = options.issuance.totalSupply; _this._tokenFeeBalance = '0'; _this._symbol = options.issuance.symbol; _this._name = options.issuance.name; _this._issuerInfo = options.issuance.issuerInfo; _this._feeRate = options.issuance.feeRate; _this._feeType = options.issuance.feeType; _this._controllers = options.issuance.controllersAsObject; _this._settings = options.issuance.settingsAsObject; } /** * Token Balance of the token account * * @type {string} * @private */ if (options.tokenBalance !== undefined) { _this._tokenBalance = options.tokenBalance; } else { _this._tokenBalance = '0'; } /** * Total Supply of tokens * * @type {string} * @private */ if (options.totalSupply !== undefined) { _this._totalSupply = options.totalSupply; } else { _this._totalSupply = null; } /** * Token Fee Balance * * @type {string} * @private */ if (options.tokenFeeBalance !== undefined) { _this._tokenFeeBalance = options.tokenFeeBalance; } else { _this._tokenFeeBalance = '0'; } /** * Symbol of the token * * @type {string} * @private */ if (options.symbol !== undefined) { _this._symbol = options.symbol; } else { _this._symbol = null; } /** * Name of the token * * @type {string} * @private */ if (options.name !== undefined) { _this._name = options.name; } else { _this._name = 'Unknown Token'; } /** * Issuer Info of the token * @type {string} * @private */ if (options.issuerInfo !== undefined) { _this._issuerInfo = options.issuerInfo; } else { _this._issuerInfo = null; } /** * Fee Rate of the token * * @type {string} * @private */ if (options.feeRate !== undefined) { _this._feeRate = options.feeRate; } else { _this._feeRate = null; } /** * Fee Type of the token * * @type {string} * @private */ if (options.feeType !== undefined) { _this._feeType = options.feeType; } else { _this._feeType = null; } /** * Controllers of the token * * @type {string} * @private */ if (options.controllers !== undefined) { _this._controllers = options.controllers; } else { _this._controllers = null; } /** * Settings of the token * @type {Settings} * @private */ if (options.settings !== undefined) { _this._settings = options.settings; } else { _this._settings = { issuance: null, modify_issuance: null, revoke: null, modify_revoke: null, freeze: null, modify_freeze: null, adjust_fee: null, modify_adjust_fee: null, whitelist: null, modify_whitelist: null }; } /** * Account Statuses * * @type {AccountStatuses} */ if (options.accountStatuses !== undefined) { _this._accountStatuses = options.accountStatuses; } else { _this._accountStatuses = {}; } return _this; } Object.defineProperty(TokenAccount.prototype, "type", { /** * The type of the account (LogosAccount or TokenAccount) * @type {string} */ get: function () { return 'TokenAccount'; }, enumerable: true, configurable: true }); Object.defineProperty(TokenAccount.prototype, "tokenID", { /** * The public key of the token account * @type {string} * @readonly */ get: function () { return this.publicKey; }, enumerable: true, configurable: true }); Object.defineProperty(TokenAccount.prototype, "accountStatuses", { /** * The accounts statuses (Frozen / Whitelisted) * @type {string} * @readonly */ get: function () { return this._accountStatuses; }, set: function (statuses) { this._accountStatuses = statuses; }, enumerable: true, configurable: true }); Object.defineProperty(TokenAccount.prototype, "tokenBalance", { /** * The balance of the token in the minor token unit * @type {string} * @readonly */ get: function () { return this._tokenBalance; }, set: function (val) { this._tokenBalance = val; }, enumerable: true, configurable: true }); Object.defineProperty(TokenAccount.prototype, "totalSupply", { /** * The total supply of the token in minor token * @type {string} * @readonly */ get: function () { return this._totalSupply; }, set: function (val) { this._totalSupply = val; }, enumerable: true, configurable: true }); Object.defineProperty(TokenAccount.prototype, "tokenFeeBalance", { /** * The total supply of the token in the minor token unit * @type {string} * @readonly */ get: function () { return this._tokenFeeBalance; }, set: function (val) { this._tokenFeeBalance = val; }, enumerable: true, configurable: true }); Object.defineProperty(TokenAccount.prototype, "issuerInfo", { /** * The issuer info of the token * @type {string} */ get: function () { return this._issuerInfo; }, set: function (val) { this._issuerInfo = val; }, enumerable: true, configurable: true }); Object.defineProperty(TokenAccount.prototype, "symbol", { /** * The symbol of the token * @type {string} */ get: function () { return this._symbol; }, set: function (val) { this._symbol = val; }, enumerable: true, configurable: true }); Object.defineProperty(TokenAccount.prototype, "name", { /** * The name of the token * @type {string} */ get: function () { return this._name; }, set: function (val) { this._name = val; }, enumerable: true, configurable: true }); Object.defineProperty(TokenAccount.prototype, "feeRate", { /** * The fee rate of the token * @type {string} */ get: function () { return this._feeRate; }, set: function (val) { this._feeRate = val; }, enumerable: true, configurable: true }); Object.defineProperty(TokenAccount.prototype, "feeType", { /** * The fee type of the token * @type {feeType} */ get: function () { return this._feeType; }, set: function (val) { this._feeType = val; }, enumerable: true, configurable: true }); Object.defineProperty(TokenAccount.prototype, "settings", { /** * The settings of the token * @type {Settings} */ get: function () { return this._settings; }, set: function (val) { this._settings = val; }, enumerable: true, configurable: true }); Object.defineProperty(TokenAccount.prototype, "controllers", { /** * The controllers of the token * @type {Controller[]} */ get: function () { return this._controllers; }, set: function (val) { this._controllers = val; }, enumerable: true, configurable: true }); Object.defineProperty(TokenAccount.prototype, "decimals", { /** * The decimals of the token * @type {number} */ get: function () { try { var parsedInfo = JSON.parse(this.issuerInfo); if (parsedInfo && typeof parsedInfo.decimals !== 'undefined' && parsedInfo.decimals > 0) { return parseInt(parsedInfo.decimals); } return null; } catch (e) { return null; } }, enumerable: true, configurable: true }); TokenAccount.prototype.convertToMajor = function (minorValue) { if (this.decimals) return this.wallet.rpcClient.convert.fromTo(minorValue, 0, this.decimals); return null; }; TokenAccount.prototype.convertToMinor = function (majorValue) { if (this.decimals) return this.wallet.rpcClient.convert.fromTo(majorValue, this.decimals, 0); return null; }; /** * Checks if the account is synced * @returns {Promise<SyncedResponse>} */ TokenAccount.prototype.isSynced = function () { var _this = this; return new Promise(function (resolve) { var RPC = _this.wallet.rpcClient; RPC.accounts.info(_this.address).then(function (info) { return __awaiter(_this, void 0, void 0, function () { var synced, receiveBlock; return __generator(this, function (_a) { switch (_a.label) { case 0: synced = true; if (!(info && info.frontier)) return [3 /*break*/, 3]; this.tokenBalance = info.token_balance; this.totalSupply = info.total_supply; this.tokenFeeBalance = info.token_fee_balance; this.symbol = info.symbol; this.name = info.name; this.issuerInfo = info.issuer_info; this.feeRate = info.fee_rate; this.feeType = info.fee_type; this.controllers = Utils_1.deserializeControllers(info.controllers); this.settings = Utils_1.deserializeSettings(info.settings); this.balance = info.balance; if (info.frontier !== Utils_1.GENESIS_HASH) { if (this.chain.length === 0 || this.chain[this.chain.length - 1].hash !== info.frontier) { synced = false; } } if (!synced) return [3 /*break*/, 2]; return [4 /*yield*/, RPC.requests.info(info.receive_tip)]; case 1: receiveBlock = _a.sent(); if (this.receiveChain.length === 0 || this.receiveChain[this.receiveChain.length - 1].hash !== receiveBlock.send_hash) { synced = false; } _a.label = 2; case 2: if (synced) { if (this.wallet.validateSync) { if (this.verifyChain() && this.verifyReceiveChain()) { this.synced = synced; console.info(info.name + " has been fully synced and validated"); resolve({ account: this.address, synced: this.synced, type: 'TokenAccount' }); } } else { console.info('Finished Syncing: Requests were not validated'); this.synced = synced; resolve({ account: this.address, synced: this.synced, type: 'TokenAccount' }); } } else { this.synced = synced; resolve({ account: this.address, synced: this.synced, type: 'TokenAccount' }); } return [3 /*break*/, 4]; case 3: if (this.receiveChain.length === 0 && this.chain.length === 0) { console.info(this.address + " is empty and therefore valid"); this.synced = synced; resolve({ account: this.address, synced: this.synced, type: 'TokenAccount' }); } else { console.error(this.address + " is not opened according to the RPC. This is a critical error if in a production enviroment. On testnet this just means the network has been restarted."); this.synced = false; resolve({ account: this.address, synced: this.synced, type: 'TokenAccount', remove: true }); } _a.label = 4; case 4: return [2 /*return*/]; } }); }); }); }); }; /** * Scans the account history using RPC and updates the local chains * @returns {Promise<Account>} */ TokenAccount.prototype.sync = function () { var _this = this; return new Promise(function (resolve) { _this.synced = false; _this.chain = []; _this.receiveChain = []; var RPC = _this.wallet.rpcClient; RPC.accounts.info(_this.address).then(function (info) { if (!info || !info.type || info.type !== 'TokenAccount') { throw new Error('Invalid Address - This is not a valid token account'); } _this.tokenBalance = info.token_balance; _this.totalSupply = info.total_supply; _this.tokenFeeBalance = info.token_fee_balance; _this.symbol = info.symbol; _this.name = info.name; _this.issuerInfo = info.issuer_info; _this.feeRate = info.fee_rate; _this.feeType = info.fee_type; _this.controllers = Utils_1.deserializeControllers(info.controllers); _this.settings = Utils_1.deserializeSettings(info.settings); _this.balance = info.balance; if (_this.wallet.fullSync) { RPC.accounts.history(_this.address, -1, true).then(function (history) { if (history) { // Add Genesis to latest for (var _i = 0, _a = history.reverse(); _i < _a.length; _i++) { var requestInfo = _a[_i]; var request = _this.addConfirmedRequest(requestInfo); if (request instanceof Requests_1.AdjustUserStatus) { _this.updateAccountStatusFromRequest(request); } } if (_this.wallet.validateSync) { if (_this.verifyChain() && _this.verifyReceiveChain()) { _this.synced = true; console.info(info.name + " has been fully synced and validated"); resolve(_this); } } else { console.info('Finished Syncing: Requests were not validated'); _this.synced = true; resolve(_this); } } else { _this.synced = true; console.info(_this.address + " is empty and therefore valid"); resolve(_this); } }); } else { if (info && info.frontier && info.frontier !== Utils_1.GENESIS_HASH) { RPC.requests.info(info.frontier).then(function (val) { var request = _this.addConfirmedRequest(val); if (request !== null && !request.verify()) { throw new Error("Invalid Request from RPC sync! \n " + JSON.stringify(request.toJSON(), null, 2)); } _this.synced = true; console.info(info.name + " has been lazy synced"); resolve(_this); }); } else { _this.synced = true; console.info(_this.address + " is empty and therefore valid"); resolve(_this); } } }); }); }; /** * Updates the token account by comparing the RPC token account info with the changes in a new request * Also updates the pending balance based on the new balance and the pending chain * @param {Request} request - request that is being calculated on * @returns {void} */ TokenAccount.prototype.updateTokenInfoFromRequest = function (request) { if (request instanceof Requests_1.IssueAdditional) { this.totalSupply = big_integer_1.default(this.totalSupply).plus(big_integer_1.default(request.amount)).toString(); this.tokenBalance = big_integer_1.default(this.tokenBalance).plus(big_integer_1.default(request.amount)).toString(); } else if (request instanceof Requests_1.ChangeSetting) { this.settings[request.setting] = request.value; } else if (request instanceof Requests_1.ImmuteSetting) { this.settings["modify_" + request.setting] = false; } else if (request instanceof Requests_1.Revoke) { if (request.transaction.destination === this.address) { this.tokenBalance = big_integer_1.default(this.tokenBalance).plus(big_integer_1.default(request.transaction.amount)).toString(); } // Handle if TK account is SRC? } else if (request instanceof Requests_1.AdjustUserStatus) { this.updateAccountStatusFromRequest(request); } else if (request instanceof Requests_1.AdjustFee) { this.feeRate = request.feeRate; this.feeType = request.feeType; } else if (request instanceof Requests_1.UpdateIssuerInfo) { this.issuerInfo = request.issuerInfo; } else if (request instanceof Requests_1.UpdateController) { var updatedPrivs = Utils_1.serializeController(request.controller).privileges; if (request.action === 'remove' && updatedPrivs.length === 0) { this.controllers = this.controllers.filter(function (controller) { return controller.account !== request.controller.account; }); } else if (request.action === 'remove' && updatedPrivs.length > 0) { for (var _i = 0, _a = this.controllers; _i < _a.length; _i++) { var controller = _a[_i]; if (controller.account === request.controller.account) { for (var _b = 0, updatedPrivs_1 = updatedPrivs; _b < updatedPrivs_1.length; _b++) { var priv = updatedPrivs_1[_b]; controller.privileges[priv] = false; } } } } else if (request.action === 'add') { if (this.controllers.some(function (controller) { return controller.account === request.controller.account; })) { for (var _c = 0, _d = this.controllers; _c < _d.length; _c++) { var controller = _d[_c]; if (controller.account === request.controller.account) { for (var _e = 0, updatedPrivs_2 = updatedPrivs; _e < updatedPrivs_2.length; _e++) { var priv = updatedPrivs_2[_e]; controller.privileges[priv] = true; } } } } else { this.controllers.push(request.controller); } } } else if (request instanceof Requests_1.Burn) { this.totalSupply = big_integer_1.default(this.totalSupply).minus(big_integer_1.default(request.amount)).toString(); this.tokenBalance = big_integer_1.default(this.tokenBalance).minus(big_integer_1.default(request.amount)).toString(); } else if (request instanceof Requests_1.Distribute) { this.tokenBalance = big_integer_1.default(this.tokenBalance).minus(big_integer_1.default(request.transaction.amount)).toString(); } else if (request instanceof Requests_1.WithdrawFee) { this.tokenFeeBalance = big_integer_1.default(this.tokenFeeBalance).minus(big_integer_1.default(request.transaction.amount)).toString(); } else if (request instanceof Requests_1.WithdrawLogos) { if (request.tokenID === this.tokenID) { this.balance = big_integer_1.default(this.balance).minus(big_integer_1.default(request.transaction.amount)).minus(big_integer_1.default(request.fee)).toString(); } if (request.transaction.destination === this.address) { this.balance = big_integer_1.default(this.balance).plus(big_integer_1.default(request.transaction.amount)).toString(); } } else if (request instanceof Requests_1.Send) { for (var _f = 0, _g = request.transactions; _f < _g.length; _f++) { var transaction = _g[_f]; if (transaction.destination === this.address) { this.balance = big_integer_1.default(this.balance).plus(big_integer_1.default(transaction.amount)).toString(); } } } else if (request instanceof Requests_1.Issuance) { this.tokenBalance = request.totalSupply; // this._pendingTokenBalance = request.totalSupply this.totalSupply = request.totalSupply; // this._pendingTotalSupply = request.totalSupply this.tokenFeeBalance = '0'; this.symbol = request.symbol; this.name = request.name; this.issuerInfo = request.issuerInfo; this.feeRate = request.feeRate; this.feeType = request.feeType; this.controllers = request.controllersAsObject; this.settings = request.settingsAsObject; this.balance = '0'; this.pendingBalance = '0'; } else if (request.type === 'token_send') { if (request.tokenFee) { this.tokenFeeBalance = big_integer_1.default(this.tokenFeeBalance).plus(request.tokenFee).toString(); } } if (request.type !== 'send' && request.type !== 'issuance' && request.type !== 'token_send' && request.type !== 'withdraw_logos') { this.balance = big_integer_1.default(this.balance).minus(big_integer_1.default(request.fee)).toString(); } }; /** * Validates if the token account contains the controller * * @param {string} address - Address of the logos account you are checking if they are a controller * @returns {boolean} */ TokenAccount.prototype.isController = function (address) { for (var _i = 0, _a = this.controllers; _i < _a.length; _i++) { var controller = _a[_i]; if (controller.account === address) { return true; } } return false; }; /** * Validates if the token has the setting * * @param {Setting} setting - Token setting you are checking * @returns {boolean} */ TokenAccount.prototype.hasSetting = function (setting) { return Boolean(this.settings[setting]); }; /** * Validates if the token account contains the controller and the controller has the specified privilege * * @param {string} address - Address of the controller you are checking * @param {privilege} privilege - Privilege you are checking for * @returns {boolean} */ TokenAccount.prototype.controllerPrivilege = function (address, privilege) { for (var _i = 0, _a = this.controllers; _i < _a.length; _i++) { var controller = _a[_i]; if (controller.account === address) { return controller.privileges[privilege]; } } return false; }; /** * Validates if the account has enough token funds to complete the transaction * * @param {string} address - Address of the controller you are checking * @param {string} amount - Amount you are checking for * @returns {Promise<boolean>} */ TokenAccount.prototype.accountHasFunds = function (address, amount) { return __awaiter(this, void 0, void 0, function () { var RPC, info; return __generator(this, function (_a) { switch (_a.label) { case 0: if (!!this.wallet.rpc) return [3 /*break*/, 1]; console.warn('Cannot client-side validate if an account has funds without RPC enabled'); return [2 /*return*/, true]; case 1: RPC = this.wallet.rpcClient; return [4 /*yield*/, RPC.accounts.info(address)]; case 2: info = _a.sent(); return [2 /*return*/, big_integer_1.default(info.tokens[this.tokenID].balance).greaterOrEquals(big_integer_1.default(amount))]; } }); }); }; /** * Validates if the account is a valid destination to send token funds to * * @param {string} address - Address of the controller you are checking * @returns {Promise<boolean>} */ TokenAccount.prototype.validTokenDestination = function (address) { return __awaiter(this, void 0, void 0, function () { var RPC, info, tokenInfo; return __generator(this, function (_a) { switch (_a.label) { case 0: if (!!this.wallet.rpc) return [3 /*break*/, 1]; console.warn('Cannot client-side validate destination without RPC enabled'); return [2 /*return*/, true]; case 1: RPC = this.wallet.rpcClient; return [4 /*yield*/, RPC.accounts.info(address)]; case 2: info = _a.sent(); if (info.type !== 'LogosAccount') return [2 /*return*/, false]; tokenInfo = null; if (info && info.tokens && info.tokens[this.tokenID]) { tokenInfo = info.tokens[this.tokenID]; } if (!tokenInfo && this.hasSetting('whitelist')) { return [2 /*return*/, false]; } else if (!tokenInfo && !this.hasSetting('whitelist')) { return [2 /*return*/, true]; } else if (this.hasSetting('whitelist') && tokenInfo.whitelisted === 'false') { return [2 /*return*/, false]; } else if (tokenInfo.frozen === 'true') { return [2 /*return*/, false]; } else { return [2 /*return*/, true]; } _a.label = 3; case 3: return [2 /*return*/]; } }); }); }; /** * Validates that the account has enough funds at the current time to publish the request * * @param {Request} request - Request information from the RPC or MQTT * @returns {Promise<boolean>} */ TokenAccount.prototype.validateRequest = function (request) { return __awaiter(this, void 0, void 0, function () { return __generator(this, function (_a) { switch (_a.label) { case 0: if (!big_integer_1.default(this.balance).minus(request.fee).lesser(0)) return [3 /*break*/, 1]; console.error('Invalid Request: Token Account does not have enough Logos to afford the fee perform token opperation'); return [2 /*return*/, false]; case 1: if (!(request instanceof Requests_1.IssueAdditional)) return [3 /*break*/, 2]; if (big_integer_1.default(this.totalSupply).plus(big_integer_1.default(request.amount)).greater(big_integer_1.default(Utils_1.MAXUINT128))) { console.error('Invalid Issue Additional Request: Total Supply would exceed MAXUINT128'); return [2 /*return*/, false]; } else if (!this.hasSetting('issuance')) { console.error('Invalid Issue Additional Request: Token does not allow issuance'); return [2 /*return*/, false]; } else if (!this.controllerPrivilege(request.originAccount, 'issuance')) { console.error('Invalid Issue Additional Request: Controller does not have permission to issue additional tokens'); return [2 /*return*/, false]; } else { return [2 /*return*/, true]; } return [3 /*break*/, 27]; case 2: if (!(request instanceof Requests_1.ChangeSetting)) return [3 /*break*/, 3]; if (!this.hasSetting(this.settingToModify(request.setting))) { console.error("Invalid Change Setting Request: " + this.name + " does not allow changing " + request.setting); return [2 /*return*/, false]; } else if (!this.controllerPrivilege(request.originAccount, this.settingToChange(request.setting))) { console.error("Invalid Change Setting Request: Controller does not have permission to change " + request.setting); return [2 /*return*/, false]; } else { return [2 /*return*/, true]; } return [3 /*break*/, 27]; case 3: if (!(request instanceof Requests_1.ImmuteSetting)) return [3 /*break*/, 4]; if (!this.hasSetting(this.settingToModify(request.setting))) { console.error("Invalid Immute Setting Request: " + request.setting + " is already immuatable"); return [2 /*return*/, false]; } else if (!this.controllerPrivilege(request.originAccount, this.settingToChangeModify(request.setting))) { console.error("Invalid Immute Setting Request: Controller does not have permission to immute " + request.setting); return [2 /*return*/, false]; } else { return [2 /*return*/, true]; } return [3 /*break*/, 27]; case 4: if (!(request instanceof Requests_1.Revoke)) return [3 /*break*/, 11]; if (!!this.hasSetting('revoke')) return [3 /*break*/, 5]; console.error("Invalid Revoke Request: " + this.name + " does not support revoking accounts"); return [2 /*return*/, false]; case 5: if (!!this.controllerPrivilege(request.originAccount, 'revoke')) return [3 /*break*/, 6]; console.error('Invalid Revoke Request: Controller does not have permission to issue revoke requests'); return [2 /*return*/, false]; case 6: return [4 /*yield*/, !this.accountHasFunds(request.source, request.transaction.amount)]; case 7: if (!_a.sent()) return [3 /*break*/, 8]; console.error("Invalid Revoke Request: Source account does not have sufficient " + this.symbol + " to complete this request"); return [2 /*return*/, false]; case 8: return [4 /*yield*/, !this.validTokenDestination(request.transaction.destination)]; case 9: if (_a.sent()) { console.error("Invalid Revoke Request: Destination does not have permission to receive " + this.symbol); return [2 /*return*/, false]; } else { return [2 /*return*/, true]; } _a.label = 10; case 10: return [3 /*break*/, 27]; case 11: if (!(request instanceof Requests_1.AdjustUserStatus)) return [3 /*break*/, 12]; if (request.status === 'frozen' || request.status === 'unfrozen') { if (!this.hasSetting('freeze')) { console.error("Invalid Adjust User Status: " + this.name + " does not support freezing accounts"); return [2 /*return*/, false]; } else if (!this.controllerPrivilege(request.originAccount, 'freeze')) { console.error('Invalid Adjust User Status Request: Controller does not have permission to freeze accounts'); return [2 /*return*/, false]; } else { return [2 /*return*/, true]; } } else if (request.status === 'whitelisted' || request.status === 'not_whitelisted') { if (!this.hasSetting('whitelist')) { console.error("Invalid Adjust User Status: " + this.name + " does not require whitelisting accounts"); return [2 /*return*/, false]; } else if (!this.controllerPrivilege(request.originAccount, 'revoke')) { console.error('Invalid Adjust User Status Request: Controller does not have permission to whitelist accounts'); return [2 /*return*/, false]; } else { return [2 /*return*/, true]; } } else { console.error("Invalid Adjust User Status: " + request.status + " is not a valid status"); return [2 /*return*/, false]; } return [3 /*break*/, 27]; case 12: if (!(request instanceof Requests_1.AdjustFee)) return [3 /*break*/, 13]; if (!this.hasSetting('adjust_fee')) { console.error("Invalid Adjust Fee Request: " + this.name + " does not allow changing the fee type or fee rate"); return [2 /*return*/, false]; } else if (!this.controllerPrivilege(request.originAccount, 'adjust_fee')) { console.error('Invalid Adjust Fee Request: Controller does not have permission to freeze accounts'); return [2 /*return*/, false]; } else { return [2 /*return*/, true]; } return [3 /*break*/, 27]; case 13: if (!(request instanceof Requests_1.UpdateIssuerInfo)) return [3 /*break*/, 14]; if (!this.controllerPrivilege(request.originAccount, 'update_issuer_info')) { console.error('Invalid Update Issuer Info Request: Controller does not have permission to update the issuer info'); return [2 /*return*/, false]; } else { return [2 /*return*/, true]; } return [3 /*break*/, 27]; case 14: if (!(request instanceof Requests_1.UpdateController)) return [3 /*break*/, 15]; if (!this.controllerPrivilege(request.originAccount, 'update_controller')) { console.error('Invalid Update Controller Request: Controller does not have permission to update controllers'); return [2 /*return*/, false]; } else if (this.controllers.length === 10 && request.action === 'add' && !this.isController(request.controller.account)) { console.error("Invalid Update Controller Request: " + this.name + " already has 10 controllers you must remove one first"); return [2 /*return*/, false]; } else { return [2 /*return*/, true]; } return [3 /*break*/, 27]; case 15: if (!(request instanceof Requests_1.Burn)) return [3 /*break*/, 16]; if (!this.controllerPrivilege(request.originAccount, 'burn')) { console.error('Invalid Burn Request: Controller does not have permission to burn tokens'); return [2 /*return*/, false]; } else if (big_integer_1.default(this.tokenBalance).lesser(big_integer_1.default(request.amount))) { console.error('Invalid Burn Request: the token balance of the token account is less than the amount of tokens you are trying to burn'); return [2 /*return*/, false]; } else { return [2 /*return*/, true]; } return [3 /*break*/, 27]; case 16: if (!(request instanceof Requests_1.Distribute)) return [3 /*break*/, 21]; if (!!this.controllerPrivilege(request.originAccount, 'distribute')) return [3 /*break*/, 17]; console.error('Invalid Distribute Request: Controller does not have permission to distribute tokens'); return [2 /*return*/, false]; case 17: if (!big_integer_1.default(this.tokenBalance).lesser(big_integer_1.default(request.transaction.amount))) return [3 /*break*/, 18]; console.error("Invalid Distribute Request: Token account does not have sufficient " + this.symbol + " to distribute"); return [2 /*return*/, false]; case 18: return [4 /*yield*/, !this.validTokenDestination(request.transaction.destination)]; case 19: if (_a.sent()) { console.error("Invalid Distribute Request: Destination does not have permission to receive " + this.symbol); return [2 /*return*/, false]; } else { return [2 /*return*/, true]; } _a.label = 20; case 20: return [3 /*break*/, 27]; case 21: if (!(request instanceof Requests_1.WithdrawFee)) return [3 /*break*/, 26]; if (!!this.controllerPrivilege(request.originAccount, 'withdraw_fee')) return [3 /*break*/, 22]; console.error('Invalid Withdraw Fee Request: Controller does not have permission to withdraw fee'); return [2 /*return*/, false]; case 22: if (!big_integer_1.default(this.tokenFeeBalance).lesser(big_integer_1.default(request.transaction.amount))) return [3 /*break*/, 23]; console.error('Invalid Withdraw Fee Request: Token account does not have a sufficient token fee balance to withdraw the specified amount'); return [2 /*return*/, false]; case 23: return [4 /*yield*/, !this.validTokenDestination(request.transaction.destination)]; case 24: if (_a.sent()) { console.error("Invalid Withdraw Fee Request: Destination does not have permission to receive " + this.symbol); return [2 /*return*/, false]; } else { return [2 /*return*/, true]; } _a.label = 25; case 25: return [3 /*break*/, 27]; case 26: if (request instanceof Requests_1.WithdrawLogos) { if (!this.controllerPrivilege(request.originAccount, 'withdraw_logos')) { console.error('Invalid Withdraw Logos Request: Controller does not have permission to withdraw logos'); return [2 /*return*/, false]; } else if (big_integer_1.default(this.balance).lesser(big_integer_1.default(request.transaction.amount).plus(big_integer_1.default(request.fee)))) { console.error('Invalid Withdraw Logos Request: Token account does not have sufficient balance to withdraw the specified amount + the minimum logos fee'); return [2 /*return*/, false]; } else { return [2 /*return*/, true]; } } else { return [2 /*return*/, false]; } _a.label = 27; case 27: return [2 /*return*/]; } }); }); }; TokenAccount.prototype.settingToModify = function (setting) {