UNPKG

@logosnetwork/logos-webwallet-sdk

Version:

Create Logos wallets with or without a full Logos node

1,031 lines (1,030 loc) 90.2 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 __assign = (this && this.__assign) || function () { __assign = Object.assign || function(t) { for (var s, i = 1, n = arguments.length; i < n; i++) { s = arguments[i]; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; } return t; }; return __assign.apply(this, arguments); }; 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 Utils_1 = require("./Utils/Utils"); var big_integer_1 = __importDefault(require("big-integer")); var Account_1 = __importDefault(require("./Account")); var Requests_1 = require("./Requests"); /** * ## Logos Account * This class is the base class of an account on the Logos Network. * The most common uses for this account is to check the balance, history, and create new requests from this account as the origin. */ var LogosAccount = /** @class */ (function (_super) { __extends(LogosAccount, _super); /** * ### Instantiating * ```typescript * const LogosAccount = new LogosAccount({ * label: null, * address: null, * publicKey: null, * balance: '0', * pendingBalance: '0', * wallet: null, * chain: [], * receiveChain: [], * pendingChain: [], * privateKey: null * tokenBalances: {}, * tokens: [], * pendingTokenBalances: {}, * index: null * }) * ``` * * All logos account options are optional defaults are shown in the example above * * |Account Options| Description | * |--|--| * | label | Account label e.g. Checking Account | * | address | Address is the lgs_ string | * | publicKey | Public key of the account | * | balance | Balance of the account in the minor unit of Logos | * | pendingBalance | balance of the account including pending transaction in the minor unit of Logos | * | wallet | reference back to the parent wallet class | * | chain | Array of [[Request]] that are confirmed on this account's send chain | * | receiveChain | Array of [[Request]] that are confirmed on this account's receive chain | * | pendingChain | Array of [[Request]] that are *not* confirmed on this account's send chain | * | [[privateKey]] | Private key of the account used to sign transactions | * | [[tokenBalances]] | Balances tokens that this account has in their | * | [[tokens]] | Array of token addresses associated with this account | * | [[pendingTokenBalances]] | Unconfirmed balances of the tokens | * | [[index]] | index of the account | */ function LogosAccount(options) { if (options === void 0) { options = { privateKey: null, tokenBalances: {}, tokens: [], pendingTokenBalances: {}, index: null }; } var _this = _super.call(this, options) || this; /** * Deterministic Key Index used to generate this account - null means generated explicitly * * @type {number} * @private */ if (options.index !== undefined) { _this._index = options.index; } else { _this._index = null; } /** * Private Key of this account * @type {string} * @private */ if (options.privateKey !== undefined) { _this._privateKey = options.privateKey; } else { _this._privateKey = null; } /** * Tokens that are associated with your account * @type {string[]} * @private */ if (options.tokens !== undefined) { _this._tokens = options.tokens; } else { _this._tokens = []; } /** * Token Balance of the token account in minor unit of tokens * @type {TokenBalances} * @private */ if (options.tokenBalances !== undefined) { _this._tokenBalances = options.tokenBalances; } else { _this._tokenBalances = {}; } /** * Pending Token Balance of the token account in minor unit of tokens * * pending token balance is the token balance minus the token sends that are pending * @type {TokenBalances} * @private */ if (options.pendingTokenBalances !== undefined) { _this._pendingTokenBalances = options.pendingTokenBalances; } else { _this._pendingTokenBalances = {}; } return _this; } Object.defineProperty(LogosAccount.prototype, "type", { /** * The type of the account (LogosAccount or TokenAccount) * #### Example * ```typescript * const type = logosAccount.type * ``` */ get: function () { return 'LogosAccount'; }, enumerable: true, configurable: true }); Object.defineProperty(LogosAccount.prototype, "index", { /** * The index of the account * #### Example * ```typescript * const index = logosAccount.index * ``` */ get: function () { return this._index; }, enumerable: true, configurable: true }); Object.defineProperty(LogosAccount.prototype, "privateKey", { /** * The private key of the account * #### Example * ```typescript * const privateKey = logosAccount.privateKey * ``` */ get: function () { return this._privateKey; }, enumerable: true, configurable: true }); Object.defineProperty(LogosAccount.prototype, "tokens", { /** * Array of associated token ids to this account (full list available only with fullsync) * #### Example * ```typescript * const tokens = logosAccount.tokens * ``` */ get: function () { return this._tokens; }, enumerable: true, configurable: true }); Object.defineProperty(LogosAccount.prototype, "tokenBalances", { /** * The balance of the tokens in the minor token unit * #### Example * ```typescript * const tokenBalances = logosAccount.tokenBalances * ``` */ get: function () { return this._tokenBalances; }, enumerable: true, configurable: true }); Object.defineProperty(LogosAccount.prototype, "pendingTokenBalances", { /** * The pending token balance of the account in the minor token unit * * pending token balance is balance minus the token sends that are pending * * #### Example * ```typescript * const pendingTokenBalances = logosAccount.pendingTokenBalances * ``` */ get: function () { return this._pendingTokenBalances; }, enumerable: true, configurable: true }); /** * The balance of the given token in the minor unit and major unit (if available) * @param {string} tokenID - Token ID of the token in question, you can also send the token account address * @returns {{minor: string;major?: string}} The balance in minor unit or converted units * #### Example * ```typescript * const tokenBalance = logosAccount.tokenBalance('lgs_3q69z3kf6cq9n9smago3p1ptuyqy9pa3mdykyi9o8f7gnof47qdyxj9gejxd') * ``` */ LogosAccount.prototype.tokenBalance = function (token) { var tokenAccountKey = Utils_1.keyFromAccount(token); var tokenAddress = Utils_1.accountFromHexKey(tokenAccountKey); var minorValue = this.tokenBalances[tokenAccountKey]; if (minorValue) { var result = { minor: minorValue }; if (!this.wallet.tokenAccounts[tokenAddress]) return result; result.major = this.wallet.tokenAccounts[tokenAddress].convertToMajor(minorValue); return result; } else { return null; } }; /** * Adds a token to the accounts associated tokens if it doesn't already exist * * @param {string} tokenID - The TokenID you are associating with this account (this will be converted into a token account when stored) * @returns {string[]} Array of all the associated tokens * #### Example * ```typescript * const token = await logosAccount.addToken('lgs_3q69z3kf6cq9n9smago3p1ptuyqy9pa3mdykyi9o8f7gnof47qdyxj9gejxd') * ``` */ LogosAccount.prototype.addToken = function (tokenID) { return __awaiter(this, void 0, void 0, function () { var tokenAddress; return __generator(this, function (_a) { switch (_a.label) { case 0: tokenAddress = Utils_1.accountFromHexKey(tokenID); if (!!this.tokens.includes(tokenAddress)) return [3 /*break*/, 2]; this.tokens.push(tokenAddress); if (!this.wallet.tokenSync) return [3 /*break*/, 2]; return [4 /*yield*/, this.wallet.createTokenAccount(tokenAddress)]; case 1: _a.sent(); _a.label = 2; case 2: return [2 /*return*/, this.tokens]; } }); }); }; /** * Checks if the account is synced * @returns {Promise<SyncedResponse>} * #### Example * ```typescript * const isSynced = await logosAccount.isSynced() * ``` */ LogosAccount.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]; 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) { this.updateBalancesFromChain(); if (this.wallet.validateSync) { if (this.verifyChain() && this.verifyReceiveChain()) { this.synced = synced; console.info(this.address + " has been fully synced and validated"); resolve({ account: this.address, synced: this.synced, type: 'LogosAccount' }); } } else { console.info('Finished Syncing: Requests were not validated'); this.synced = synced; resolve({ account: this.address, synced: this.synced, type: 'LogosAccount' }); } } else { this.synced = synced; resolve({ account: this.address, synced: this.synced, type: 'LogosAccount' }); } 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: 'LogosAccount' }); } 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: 'LogosAccount' }); } _a.label = 4; case 4: return [2 /*return*/]; } }); }); }); }); }; /** * Scans the account history using RPC and updates the local chain * * @returns {Promise<Account>} * #### Example * ```typescript * const isSynced = await logosAccount.sync() * ``` */ LogosAccount.prototype.sync = function () { var _this = this; return new Promise(function (resolve) { _this.synced = false; _this.chain = []; _this.receiveChain = []; _this.pendingChain = []; _this._tokenBalances = {}; _this.balance = '0'; _this.pendingBalance = '0'; _this._tokens = []; _this._pendingTokenBalances = {}; var RPC = _this.wallet.rpcClient; if (_this.wallet.fullSync) { RPC.accounts.history(_this.address, -1, true).then(function (history) { return __awaiter(_this, void 0, void 0, function () { var _i, _a, requestInfo; return __generator(this, function (_b) { switch (_b.label) { case 0: if (!history) return [3 /*break*/, 5]; _i = 0, _a = history.reverse(); _b.label = 1; case 1: if (!(_i < _a.length)) return [3 /*break*/, 4]; requestInfo = _a[_i]; return [4 /*yield*/, this.addConfirmedRequest(requestInfo)]; case 2: _b.sent(); _b.label = 3; case 3: _i++; return [3 /*break*/, 1]; case 4: this.updateBalancesFromChain(); if (this.wallet.validateSync) { if (this.verifyChain() && this.verifyReceiveChain()) { this.synced = true; console.info(this.address + " has been fully synced and validated"); resolve(this); } } else { console.info('Finished Syncing: Requests were not validated'); this.synced = true; resolve(this); } return [3 /*break*/, 6]; case 5: this.synced = true; console.info(this.address + " is empty and therefore valid"); resolve(this); _b.label = 6; case 6: return [2 /*return*/]; } }); }); }); } else { RPC.accounts.info(_this.address).then(function (info) { if (info && info.frontier && info.frontier !== Utils_1.GENESIS_HASH) { RPC.requests.info(info.frontier).then(function (val) { return __awaiter(_this, void 0, void 0, function () { var request, tokenBalances, _i, _a, _b, tokenID, accountInfo; return __generator(this, function (_c) { switch (_c.label) { case 0: return [4 /*yield*/, this.addConfirmedRequest(val)]; case 1: request = _c.sent(); if (request !== null && !request.verify()) { throw new Error("Invalid Request from RPC sync! \n " + JSON.stringify(request.toJSON(), null, 2)); } if (info.balance) { this.balance = info.balance; this.pendingBalance = info.balance; } tokenBalances = {}; if (info.tokens) { for (_i = 0, _a = Object.entries(info.tokens); _i < _a.length; _i++) { _b = _a[_i], tokenID = _b[0], accountInfo = _b[1]; this.addToken(tokenID); tokenBalances[tokenID] = accountInfo.balance; } this._tokenBalances = __assign({}, tokenBalances); this._pendingTokenBalances = __assign({}, tokenBalances); } this.synced = true; console.info(this.address + " has been lazy synced"); resolve(this); return [2 /*return*/]; } }); }); }); } else { if (info) { if (info.balance) { _this.balance = info.balance; _this.pendingBalance = info.balance; } var tokenBalances = {}; if (info.tokens) { for (var _i = 0, _a = Object.entries(info.tokens); _i < _a.length; _i++) { var _b = _a[_i], tokenID = _b[0], accountInfo = _b[1]; _this.addToken(tokenID); tokenBalances[tokenID] = accountInfo.balance; } _this._tokenBalances = __assign({}, tokenBalances); _this._pendingTokenBalances = __assign({}, tokenBalances); } } _this.synced = true; console.info(_this.address + " is empty and therefore valid"); resolve(_this); } }); } }); }; /** * Updates the balances of the account by traversing the chain * @returns {void} * #### Example * ```typescript * logosAccount.updateBalancesFromChain() * ``` */ LogosAccount.prototype.updateBalancesFromChain = function () { var sum = big_integer_1.default(0); var tokenSums = {}; for (var _i = 0, _a = this.receiveChain; _i < _a.length; _i++) { var request = _a[_i]; if (request instanceof Requests_1.Send) { for (var _b = 0, _c = request.transactions; _b < _c.length; _b++) { var transaction = _c[_b]; if (transaction.destination === this.address) { sum = sum.plus(big_integer_1.default(transaction.amount)); } } } else if (request instanceof Requests_1.WithdrawLogos) { if (request.transaction.destination === this.address) { sum = sum.plus(big_integer_1.default(request.transaction.amount)); } } else if (request instanceof Requests_1.TokenSend) { for (var _d = 0, _e = request.transactions; _d < _e.length; _d++) { var transaction = _e[_d]; if (transaction.destination === this.address) { tokenSums[request.tokenID] = big_integer_1.default(tokenSums[request.tokenID]).plus(big_integer_1.default(transaction.amount)).toString(); } } } else if (request instanceof Requests_1.Distribute || request instanceof Requests_1.WithdrawFee || request instanceof Requests_1.Revoke) { if (request.transaction.destination === this.address) { tokenSums[request.tokenID] = big_integer_1.default(tokenSums[request.tokenID]).plus(big_integer_1.default(request.transaction.amount)).toString(); } if (request instanceof Requests_1.Revoke && request.source === this.address) { tokenSums[request.tokenID] = big_integer_1.default(tokenSums[request.tokenID]).minus(big_integer_1.default(request.transaction.amount)).toString(); } } } for (var _f = 0, _g = this.chain; _f < _g.length; _f++) { var request = _g[_f]; if (request instanceof Requests_1.Send) { sum = sum.minus(big_integer_1.default(request.totalAmount)).minus(big_integer_1.default(request.fee)); } else if (request instanceof Requests_1.TokenSend) { tokenSums[request.tokenID] = big_integer_1.default(tokenSums[request.tokenID]).minus(big_integer_1.default(request.totalAmount)).minus(big_integer_1.default(request.tokenFee)).toString(); sum = sum.minus(big_integer_1.default(request.fee)); } else if (request instanceof Requests_1.Issuance) { sum = sum.minus(big_integer_1.default(request.fee)); } } this.balance = sum.toString(); this._tokenBalances = __assign({}, tokenSums); for (var _h = 0, _j = this.pendingChain; _h < _j.length; _h++) { var pendingRequest = _j[_h]; if (pendingRequest instanceof Requests_1.Send) { sum = sum.minus(big_integer_1.default(pendingRequest.totalAmount)).minus(big_integer_1.default(pendingRequest.fee)); for (var _k = 0, _l = pendingRequest.transactions; _k < _l.length; _k++) { var transaction = _l[_k]; if (transaction.destination === this.address) { sum = sum.plus(big_integer_1.default(transaction.amount)); } } } else if (pendingRequest instanceof Requests_1.TokenSend) { sum = sum.minus(big_integer_1.default(pendingRequest.fee)); tokenSums[pendingRequest.tokenID] = big_integer_1.default(tokenSums[pendingRequest.tokenID]).minus(big_integer_1.default(pendingRequest.totalAmount)).minus(big_integer_1.default(pendingRequest.tokenFee)).toString(); for (var _m = 0, _o = pendingRequest.transactions; _m < _o.length; _m++) { var transaction = _o[_m]; if (transaction.destination === this.address) { tokenSums[pendingRequest.tokenID] = big_integer_1.default(tokenSums[pendingRequest.tokenID]).plus(big_integer_1.default(transaction.amount)).toString(); } } } else if (pendingRequest.type === 'issuance') { sum = sum.minus(big_integer_1.default(pendingRequest.fee)); } } this.pendingBalance = sum.toString(); this._pendingTokenBalances = __assign({}, tokenSums); }; /** * Updates the balances of the account by doing math on the previous balance when given 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 * #### Example * ```typescript * logosAccount.updateBalancesFromRequest() * ``` */ LogosAccount.prototype.updateBalancesFromRequest = function (request) { var sum = big_integer_1.default(this.balance); var tokenSums = this.tokenBalances; if (request instanceof Requests_1.Send) { if (request.originAccount === this.address) { sum = sum.minus(big_integer_1.default(request.totalAmount)).minus(big_integer_1.default(request.fee)); } for (var _i = 0, _a = request.transactions; _i < _a.length; _i++) { var transaction = _a[_i]; if (transaction.destination === this.address) { sum = sum.plus(big_integer_1.default(transaction.amount)); } } } else if (request instanceof Requests_1.TokenSend) { sum = sum.minus(big_integer_1.default(request.fee)); if (request.originAccount === this.address) { tokenSums[request.tokenID] = big_integer_1.default(tokenSums[request.tokenID]).minus(big_integer_1.default(request.totalAmount)).minus(big_integer_1.default(request.tokenFee)).toString(); } for (var _b = 0, _c = request.transactions; _b < _c.length; _b++) { var transaction = _c[_b]; if (transaction.destination === this.address) { tokenSums[request.tokenID] = big_integer_1.default(tokenSums[request.tokenID]).plus(big_integer_1.default(transaction.amount)).toString(); } } } else if (request instanceof Requests_1.Issuance) { sum = sum.minus(big_integer_1.default(request.fee)); } else if (request instanceof Requests_1.WithdrawLogos) { if (request.transaction.destination === this.address) { sum = sum.plus(big_integer_1.default(request.transaction.amount)); } } else if (request instanceof Requests_1.Distribute || request instanceof Requests_1.WithdrawFee || request instanceof Requests_1.Revoke) { if (request.transaction.destination === this.address) { tokenSums[request.tokenID] = big_integer_1.default(tokenSums[request.tokenID]).plus(big_integer_1.default(request.transaction.amount)).toString(); } if (request instanceof Requests_1.Revoke && request.source === this.address) { tokenSums[request.tokenID] = big_integer_1.default(tokenSums[request.tokenID]).minus(big_integer_1.default(request.transaction.amount)).toString(); } } this.balance = sum.toString(); this._tokenBalances = __assign({}, tokenSums); for (var _d = 0, _e = this.pendingChain; _d < _e.length; _d++) { var pendingRequest = _e[_d]; if (pendingRequest instanceof Requests_1.Send) { sum = sum.minus(big_integer_1.default(pendingRequest.totalAmount)).minus(big_integer_1.default(pendingRequest.fee)); for (var _f = 0, _g = pendingRequest.transactions; _f < _g.length; _f++) { var transaction = _g[_f]; if (transaction.destination === this.address) { sum = sum.plus(big_integer_1.default(transaction.amount)); } } } else if (pendingRequest instanceof Requests_1.TokenSend) { sum = sum.minus(big_integer_1.default(pendingRequest.fee)); tokenSums[pendingRequest.tokenID] = big_integer_1.default(tokenSums[pendingRequest.tokenID]).minus(big_integer_1.default(pendingRequest.totalAmount)).minus(big_integer_1.default(pendingRequest.tokenFee)).toString(); for (var _h = 0, _j = pendingRequest.transactions; _h < _j.length; _h++) { var transaction = _j[_h]; if (transaction.destination === this.address) { tokenSums[pendingRequest.tokenID] = big_integer_1.default(tokenSums[pendingRequest.tokenID]).plus(big_integer_1.default(transaction.amount)).toString(); } } } else if (pendingRequest.type === 'issuance') { sum = sum.minus(big_integer_1.default(pendingRequest.fee)); } } this.pendingBalance = sum.toString(); this._pendingTokenBalances = __assign({}, tokenSums); }; /** * Creates a request object from the mqtt info and adds the request to the appropriate chain * * @param {RequestOptions} requestInfo - Request information from the RPC or MQTT * #### Example * ```typescript * logosAccount.addConfirmedRequest([[RpcRequest]]) * ``` */ LogosAccount.prototype.addConfirmedRequest = function (requestInfo) { return __awaiter(this, void 0, void 0, function () { var request, _i, _a, trans; return __generator(this, function (_b) { switch (_b.label) { case 0: request = null; if (!requestInfo.token_id) return [3 /*break*/, 2]; return [4 /*yield*/, this.addToken(requestInfo.token_id)]; case 1: _b.sent(); _b.label = 2; case 2: if (requestInfo.type === 'send' || requestInfo.type === 'token_send') { if (requestInfo.type === 'send') { request = new Requests_1.Send(requestInfo); } else { request = new Requests_1.TokenSend(requestInfo); } // If this request was created by us // add the request to confirmed chain if (request.originAccount === this.address) { this.addToSendChain(request); } // If the request has transactions pointed to us // add the request to the receive chain if (request.transactions && request.transactions.length > 0) { for (_i = 0, _a = request.transactions; _i < _a.length; _i++) { trans = _a[_i]; if (trans.destination === this.address) { this.addToReceiveChain(request); break; } } } return [2 /*return*/, request]; } else if (requestInfo.type === 'issuance') { request = new Requests_1.Issuance(requestInfo); this.addToSendChain(request); return [2 /*return*/, request]; } else if (requestInfo.type === 'distribute') { request = new Requests_1.Distribute(requestInfo); this.addToReceiveChain(request); return [2 /*return*/, request]; } else if (requestInfo.type === 'withdraw_fee') { request = new Requests_1.WithdrawFee(requestInfo); this.addToReceiveChain(request); return [2 /*return*/, request]; } else if (requestInfo.type === 'revoke') { request = new Requests_1.Revoke(requestInfo); this.addToReceiveChain(request); return [2 /*return*/, request]; } else if (requestInfo.type === 'withdraw_logos') { request = new Requests_1.WithdrawLogos(requestInfo); this.addToReceiveChain(request); return [2 /*return*/, request]; } else { console.error("Error processing new request for logos account " + this.address + " unknown block type: " + requestInfo.type + " hash: " + requestInfo.hash); return [2 /*return*/, null]; } return [2 /*return*/]; } }); }); }; /** * Removes all pending requests from the pending chain * #### Example * ```typescript * logosAccount.removePendingRequests() * ``` */ LogosAccount.prototype.removePendingRequests = function () { _super.prototype.removePendingRequests.call(this); this._pendingTokenBalances = __assign({}, this.tokenBalances); }; /** * Validates that the account has enough funds at the current time to publish the request * * @param {Request} request - Request Class * #### Example * ```typescript * await logosAccount.validateRequest(REQUEST) * ``` */ LogosAccount.prototype.validateRequest = function (request) { return __awaiter(this, void 0, void 0, function () { var tokenAccount; return __generator(this, function (_a) { switch (_a.label) { case 0: if (!(request instanceof Requests_1.Send)) return [3 /*break*/, 1]; if (big_integer_1.default(this.balance).minus(big_integer_1.default(request.totalAmount)).minus(request.fee).lesser(0)) { console.error('Invalid Request: Not Enough Funds including fee to send that amount'); return [2 /*return*/, false]; } return [2 /*return*/, true]; case 1: if (!(request instanceof Requests_1.TokenSend)) return [3 /*break*/, 3]; return [4 /*yield*/, this.getTokenAccount(request.tokenID)]; case 2: tokenAccount = _a.sent(); if (big_integer_1.default(this.balance).minus(request.fee).lesser(0)) { console.error('Invalid Token Send Request: Not Enough Logos to pay the logos fee for token sends'); return [2 /*return*/, false]; } if (!this.tokenBalances[tokenAccount.tokenID]) { console.error('Invalid Token Send Request: User doesn\'t have a token account with the specified token'); return [2 /*return*/, false]; } if (tokenAccount.feeType === 'flat' && big_integer_1.default(tokenAccount.feeRate).greater(request.tokenFee)) { console.error("Invalid Token Send Request: Requests token is less than the required flat token fee of " + tokenAccount.feeRate); return [2 /*return*/, false]; } if (tokenAccount.feeType === 'percentage' && big_integer_1.default(request.totalAmount) .multiply(big_integer_1.default(tokenAccount.feeRate)) .divide(100) .greater(big_integer_1.default(request.tokenFee))) { console.error("Invalid Token Send Request: Requests token is less than the required percentage token fee of " + tokenAccount.feeRate + "%"); return [2 /*return*/, false]; } if (big_integer_1.default(this.tokenBalances[tokenAccount.tokenID]).minus(big_integer_1.default(request.totalAmount)).minus(big_integer_1.default(request.tokenFee)).lesser(0)) { console.error('Invalid Token Send Request: Not Enough Token to pay the token fee for token sends'); return [2 /*return*/, false]; } return [2 /*return*/, true]; case 3: if (request.type === 'issuance') { if (big_integer_1.default(this.balance).minus(request.fee).lesser(0)) { console.error('Invalid Issuance Request: Account does not have enough Logos to afford the fee to broadcast an issuance'); return [2 /*return*/, false]; } return [2 /*return*/, true]; } _a.label = 4; case 4: return [2 /*return*/, false]; } }); }); }; /** * Adds the request to the pending chain and publishes it * * @param {Request} request - Request information from the RPC or MQTT * @throws An exception if the pending balance is less than the required amount to adjust a users status * #### Example * ```typescript * const request = await logosAccount.addRequest(REQUEST) * ``` */ LogosAccount.prototype.addRequest = function (request) { return __awaiter(this, void 0, void 0, function () { return __generator(this, function (_a) { request.sign(this.privateKey); return [2 /*return*/, _super.prototype.addRequest.call(this, request)]; }); }); }; /** * Creates a request from the specified information * * @param {Transaction[]} transactions - The account destinations and amounts you wish to send them * @throws An exception if the account has not been synced * @throws An exception if the pending balance is less than the required amount to do a send * @throws An exception if the request is rejected by the RPC * #### Example * ```typescript * const request = await logosAccount.createSendRequest([ * { * destination: 'lgs_3e3j5tkog48pnny9dmfzj1r16pg8t1e76dz5tmac6iq689wyjfpiij4txtdo', * amount: '1' * } * ]) * ``` */ LogosAccount.prototype.createSendRequest = function (transactions) { return __awaiter(this, void 0, void 0, function () { var request, result; return __generator(this, function (_a) { switch (_a.label) { case 0: if (this.synced === false) throw new Error('This account has not been synced or is being synced with the RPC network'); request = new Requests_1.Send({ signature: null, previous: this.previous, fee: Utils_1.minimumFee, transactions: transactions, sequence: this.sequence, origin: this.address }); if (!this.wallet.lazyErrors) { if (big_integer_1.default(this.pendingBalance).minus(big_integer_1.default(request.totalAmount)).minus(request.fee).lesser(0)) { throw new Error('Invalid Request: Not Enough Funds including fee to send that amount'); } } this.pendingBalance = big_integer_1.default(this.pendingBalance).minus(big_integer_1.default(request.totalAmount)).minus(request.fee).toString(); return [4 /*yield*/, this.addRequest(request)]; case 1: result = _a.sent(); return [2 /*return*/, result]; } }); }); }; /** * Creates a request from the specified information * * @param {TokenIssuanceOptions} options - The options for the token creation * @throws An exception if the account has not been synced * @throws An exception if the pending balance is less than the required amount to do a token issuance * @throws An exception if the request is rejected by the RPC * #### Example * ```typescript * const request = await logosAccount.createTokenIssuanceRequest( * { * name: `UnitTestCoin`, * symbol: `UTC`, * totalSupply: '1000', * feeRate: '1', * issuerInfo: '{"decimals":0,"website":"https://github.com/LogosNetwork/logos-webwallet-sdk"}', * settings: { * issuance: true, * modify_issuance: true, * revoke: true, * modify_revoke: true, * freeze: true, * modify_freeze: true, * adjust_fee: true, * modify_adjust_fee: true, * whitelist: false, * modify_whitelist: true * }, * controllers: [{ * account: 'lgs_3e3j5tkog48pnny9dmfzj1r16pg8t1e76dz5tmac6iq689wyjfpiij4txtdo', * privileges: { * change_issuance: true, * change_modify_issuance: true, * change_revoke: true, * change_modify_revoke: true, * change_freeze: true, * change_modify_freeze: true, * change_adjust_fee: true, * change_modify_adjust_fee: true, * change_whitelist: true, * change_modify_whitelist: true, * issuance: true, * revoke: true, * freeze: true, * adjust_fee: true, * whitelist: true, * update_issuer_info: true, * update_controller: true, * burn: true, * distribute: true, * withdraw_fee: true, * withdraw_logos: true * } * }] * } * ) * ``` */ LogosAccount.prototype.createTokenIssuanceRequest = function (options) { return __awaiter(this, void 0, void 0, function () { var request, result; return __generator(this, function (_a) { switch (_a.label) { case 0: if (!options.name) throw new Error('You must pass name as a part of the TokenOptions'); if (!options.symbol) throw new Error('You must pass symbol as a part of the TokenOptions'); if (this.synced === false) throw new Error('This account has not been synced or is being synced with the RPC network'); request = new Requests_1.Issuance({ signature: null, previous: this.previous, fee: Utils_1.minimumFee, sequence: this.sequence, origin: this.address, name: options.name, symbol: options.symbol }); if (options.feeType) { request.feeType = options.feeType; } if (options.feeRate) { request.feeRate = options.feeRate; } if (options.totalSupply) { request.totalSupply = options.totalSupply; } if (options.settings) { request.settings = options.settings; } if (options.controllers) { request.controllers = options.controllers; } if (options.issuerInfo) { request.issuerInfo = options.issuerInfo; } if (!this.wallet.lazyErrors) { if (big_integer_1.default(this.pendingBalance).minus(request.fee).lesser(0)) { throw new Error('Invalid Request: Not Enough Logos to afford the fee to issue a token'); } } this.pendingBalance = big_integer_1.default(this.pendingBalance).minus(request.fee).toString(); return [4 /*yield*/, this.wallet.createTokenAccount(Utils_1.accountFromHexKey(request.tokenID), request)]; case 1: _a.sent(); return [4 /*yield*/, this.addRequest(request)]; case 2: result = _a.sent(); return [2 /*return*/, result]; } }); }); }; /** * Gets tokenAccount *