UNPKG

hive-keychain-commons

Version:

Platform-agnostic functions used in Hive Keychain mobile and extensions

272 lines (271 loc) 16 kB
"use strict"; 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 __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.ExportTransactionsUtils = void 0; const moment_1 = __importDefault(require("moment")); const index_1 = require("../index"); const transaction_utils_1 = require("./transaction.utils"); const PROPOSAL_FEE = 87; const COLLATERALIZED_CONVERT_IMMEDIATE_CONVERSION = 88; const generateCSV = (operations) => { var _a, _b; try { if (!Array.isArray(operations)) { throw new Error('Input must be an array of operations'); } if (operations.length === 0) { return 'Operation Type,Date,Transaction ID, Block number,From,To,Amount,Currency\r\n'; } let csvContent = `Operation Type,Date,Transaction ID, Block number,From,To,Amount,Currency\r\n`; for (const operation of operations) { if (!operation.operationType || !operation.datetime || !operation.transactionId || !operation.blockNumber) { throw new Error('Missing required fields in operation'); } const sanitizedValues = { operationType: String(operation.operationType).replace(/[,\r\n"]/g, ' '), datetime: String(operation.datetime).replace(/[,\r\n"]/g, ' '), transactionId: String(operation.transactionId).replace(/[,\r\n"]/g, ' '), blockNumber: String(operation.blockNumber), from: ((_a = operation.from) !== null && _a !== void 0 ? _a : 'NA').replace(/[,\r\n"]/g, ' '), to: ((_b = operation.to) !== null && _b !== void 0 ? _b : 'NA').replace(/[,\r\n"]/g, ' '), amount: String(operation.amount), currency: String(operation.currency).replace(/[,\r\n"]/g, ' '), }; csvContent += `${sanitizedValues.operationType},${sanitizedValues.datetime},${sanitizedValues.transactionId},${sanitizedValues.blockNumber},${sanitizedValues.from},${sanitizedValues.to},${sanitizedValues.amount},${sanitizedValues.currency}\r\n`; } return csvContent; } catch (error) { throw new Error(`Failed to generate CSV: ${error.message}`); } }; const fetchTransactions = (username, startDate, endDate, feedBack) => __awaiter(void 0, void 0, void 0, function* () { const MAX_LIMIT = 1000; const op = index_1.HistoryFiltersUtils.operationOrders; const operationsBitmask = index_1.HistoryFiltersUtils.makeBitMaskFilter([ op.transfer, op.interest, op.transfer_to_vesting, op.fill_vesting_withdraw, op.fill_convert_request, op.fill_collateralized_convert_request, COLLATERALIZED_CONVERT_IMMEDIATE_CONVERSION, op.fill_recurrent_transfer, op.fill_order, op.producer_reward, op.claim_reward_balance, op.escrow_release, op.account_create, op.account_create_with_delegation, op.proposal_pay, op.escrow_approve, PROPOSAL_FEE, ]); const lastTransaction = yield transaction_utils_1.TransactionUtils.getLastTransaction(username); const limit = Math.min(1000, lastTransaction); let start = lastTransaction; let rawTransactions = []; const operations = []; let forceStop = false; let percentageDuration; if (startDate) { startDate = (0, moment_1.default)(startDate).startOf('day').toDate(); } if (!endDate) { endDate = new Date(); } else { endDate = (0, moment_1.default)(endDate).endOf('day').toDate(); } if (startDate) { percentageDuration = endDate.getTime() - startDate.getTime(); } try { do { rawTransactions = yield transaction_utils_1.TransactionUtils.getTransactions(username, start, limit, operationsBitmask[0], operationsBitmask[1]); for (let i = rawTransactions.length - 1; i >= 0; i--) { const tx = rawTransactions[i]; const operationPayload = tx[1].op[1]; const operationType = tx[1].op[0]; const transactionInfo = tx[1]; // Simple timestamp handling - use original string if parsing fails let date; try { if (process.env.IS_FIREFOX) { date = (0, moment_1.default)(transactionInfo.timestamp); } else { // Try parsing with timezone marker const timestamp = transactionInfo.timestamp.endsWith('z') || transactionInfo.timestamp.endsWith('Z') ? transactionInfo.timestamp : transactionInfo.timestamp + 'Z'; date = (0, moment_1.default)(timestamp); } } catch (error) { console.error('Error parsing timestamp:', error); date = null; // Fall back to using the original string } // Use the original timestamp string if moment parsing failed const localDatetime = date && date.isValid() ? date.format('YYYY-MM-DD HH:mm:ss') : transactionInfo.timestamp; // Ensure date is valid for date comparisons const validDate = date && date.isValid() ? date : (0, moment_1.default)(new Date()); if (endDate && validDate.isSameOrAfter((0, moment_1.default)(endDate).add(1, 'day'), 'day')) continue; if (startDate && validDate.isBefore((0, moment_1.default)(startDate), 'day')) { forceStop = true; break; } const operation = { operationType, datetime: localDatetime, transactionId: transactionInfo.trx_id, blockNumber: transactionInfo.block, to: 'NA', amount: 0, currency: 'NA', from: 'NA', }; switch (operationType) { case 'transfer': case 'fill_recurrent_transfer': { const transferOperation = operationPayload; const asset = index_1.Asset.fromString(transferOperation.amount.toString()); operations.push(Object.assign(Object.assign({}, operation), { from: transferOperation.from, to: transferOperation.to, amount: asset.amount, currency: asset.symbol })); break; } case 'interest': { const asset = index_1.Asset.fromString(operationPayload.interest.toString()); operations.push(Object.assign(Object.assign({}, operation), { from: 'NA', to: operationPayload.owner, amount: asset.amount, currency: asset.symbol })); break; } case 'transfer_to_vesting': { const asset = index_1.Asset.fromString(operationPayload.amount.toString()); operations.push(Object.assign(Object.assign({}, operation), { from: operationPayload.from, to: operationPayload.to, amount: asset.amount, currency: asset.symbol })); break; } case 'fill_vesting_withdraw': { const asset = index_1.Asset.fromString(operationPayload.deposited.toString()); operations.push(Object.assign(Object.assign({}, operation), { from: operationPayload.from_account, to: operationPayload.to_account, amount: asset.amount, currency: asset.symbol })); break; } case 'fill_convert_request': { let asset = index_1.Asset.fromString(operationPayload.amount_out.toString()); operations.push(Object.assign(Object.assign({}, operation), { from: operationPayload.owner, to: operationPayload.owner, amount: asset.amount, currency: asset.symbol })); asset = index_1.Asset.fromString(operationPayload.amount_in.toString()); operations.push(Object.assign(Object.assign({}, operation), { from: operationPayload.owner, to: operationPayload.owner, amount: asset.amount, currency: asset.symbol })); break; } case 'fill_collateralized_convert_request': { let asset = index_1.Asset.fromString(operationPayload.amount_out.toString()); operations.push(Object.assign(Object.assign({}, operation), { from: operationPayload.owner, to: operationPayload.owner, amount: asset.amount, currency: asset.symbol })); asset = index_1.Asset.fromString(operationPayload.amount_in.toString()); operations.push(Object.assign(Object.assign({}, operation), { from: operationPayload.owner, to: operationPayload.owner, amount: asset.amount, currency: asset.symbol })); asset = index_1.Asset.fromString(operationPayload.excess_collateral.toString()); operations.push(Object.assign(Object.assign({}, operation), { from: operationPayload.owner, to: operationPayload.owner, amount: asset.amount, currency: asset.symbol })); break; } case 'producer_reward': { const asset = index_1.Asset.fromString(operationPayload.vesting_shares.toString()); operations.push(Object.assign(Object.assign({}, operation), { to: operationPayload.producer, amount: asset.amount, currency: asset.symbol })); break; } case 'claim_reward_balance': { let asset = index_1.Asset.fromString(operationPayload.reward_hive.toString()); if (asset.amount > 0) operations.push(Object.assign(Object.assign({}, operation), { to: operationPayload.account, amount: asset.amount, currency: asset.symbol })); asset = index_1.Asset.fromString(operationPayload.reward_hbd.toString()); if (asset.amount > 0) operations.push(Object.assign(Object.assign({}, operation), { to: operationPayload.account, amount: asset.amount, currency: asset.symbol })); asset = index_1.Asset.fromString(operationPayload.reward_vests.toString()); if (asset.amount > 0) operations.push(Object.assign(Object.assign({}, operation), { to: operationPayload.account, amount: asset.amount, currency: asset.symbol })); break; } case 'escrow_release': { let asset = index_1.Asset.fromString(operationPayload.hbd_amount.toString()); if (asset.amount > 0) operations.push(Object.assign(Object.assign({}, operation), { to: operationPayload.to, from: operationPayload.from, amount: asset.amount, currency: asset.symbol })); asset = index_1.Asset.fromString(operationPayload.hive_amount.toString()); if (asset.amount > 0) operations.push(Object.assign(Object.assign({}, operation), { to: operationPayload.to, from: operationPayload.from, amount: asset.amount, currency: asset.symbol })); break; } case 'account_create': case 'account_create_with_delegation': { const asset = index_1.Asset.fromString(operationPayload.fee.toString()); if (asset.amount > 0) operations.push(Object.assign(Object.assign({}, operation), { from: operationPayload.creator, amount: asset.amount, currency: asset.symbol })); break; } case 'proposal_pay': { const asset = index_1.Asset.fromString(operationPayload.payment.toString()); if (asset.amount > 0) operations.push(Object.assign(Object.assign({}, operation), { to: operationPayload.receiver, from: operationPayload.payer, amount: asset.amount, currency: asset.symbol })); break; } case 'fill_order': { let asset = index_1.Asset.fromString(operationPayload.current_pays.toString()); if (asset.amount > 0) operations.push(Object.assign(Object.assign({}, operation), { to: operationPayload.open_owner, from: operationPayload.current_owner, amount: asset.amount, currency: asset.symbol })); asset = index_1.Asset.fromString(operationPayload.open_pays.toString()); if (asset.amount > 0) operations.push(Object.assign(Object.assign({}, operation), { to: operationPayload.current_owner, from: operationPayload.open_owner, amount: asset.amount, currency: asset.symbol })); break; } case 'proposal_fee': { const asset = index_1.Asset.fromString(operationPayload.fee.toString()); if (asset.amount > 0) operations.push(Object.assign(Object.assign({}, operation), { to: operationPayload.treasury, from: operationPayload.creator, amount: asset.amount, currency: asset.symbol })); break; } default: console.info(`missing ${operationType}`); break; } } let percentage; if (startDate && percentageDuration) { const tx = rawTransactions[rawTransactions.length - 1]; const transactionInfo = tx[1]; const date = (0, moment_1.default)(transactionInfo.timestamp + 'z').toDate(); const passedDuration = endDate.getTime() - date.getTime(); percentage = (passedDuration / percentageDuration) * 100; } else { const index = lastTransaction - rawTransactions[rawTransactions.length - 1][0]; percentage = (index / lastTransaction) * 100; } if (feedBack) feedBack(percentage); start = Math.min(start - 1000, rawTransactions[0][0] - 1); } while (start > MAX_LIMIT && !forceStop); return operations; } catch (err) { console.error('Error while fetching transactions', err); } return undefined; }); exports.ExportTransactionsUtils = { fetchTransactions, generateCSV, };