hive-stream 3.0.4 → 3.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/streamer.js CHANGED
@@ -6,11 +6,10 @@ Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.Streamer = void 0;
7
7
  const api_1 = require("./api");
8
8
  const sqlite_adapter_1 = require("./adapters/sqlite.adapter");
9
- const utils_1 = require("@hiveio/dhive/lib/utils");
10
9
  const actions_1 = require("./actions");
11
10
  const dhive_1 = require("@hiveio/dhive");
12
11
  const bignumber_js_1 = __importDefault(require("bignumber.js"));
13
- const utils_2 = require("./utils");
12
+ const utils_1 = require("./utils");
14
13
  const builders_1 = require("./builders");
15
14
  const config_1 = require("./config");
16
15
  const hive_provider_1 = require("./providers/hive-provider");
@@ -23,6 +22,21 @@ class Streamer {
23
22
  postSubscriptions = [];
24
23
  transferSubscriptions = [];
25
24
  escrowSubscriptions = [];
25
+ voteSubscriptions = [];
26
+ delegateSubscriptions = [];
27
+ powerUpSubscriptions = [];
28
+ powerDownSubscriptions = [];
29
+ claimRewardsSubscriptions = [];
30
+ witnessVoteSubscriptions = [];
31
+ followSubscriptions = [];
32
+ reblogSubscriptions = [];
33
+ accountUpdateSubscriptions = [];
34
+ deleteCommentSubscriptions = [];
35
+ limitOrderSubscriptions = [];
36
+ savingsSubscriptions = [];
37
+ convertSubscriptions = [];
38
+ blockSubscriptions = [];
39
+ anyOperationSubscriptions = [];
26
40
  attempts = 0;
27
41
  config = (0, config_1.createConfig)();
28
42
  client;
@@ -74,16 +88,17 @@ class Streamer {
74
88
  accountCache = new Map();
75
89
  cacheTimeout = 300000; // 5 minutes
76
90
  maxCacheSize = 1000;
77
- utils = utils_2.Utils;
91
+ lastCacheCleanup = Date.now();
92
+ utils = utils_1.Utils;
78
93
  money = {
79
- parseAssetAmount: (rawAmount) => utils_2.Utils.parseAssetAmount(rawAmount),
80
- formatAmount: (amount, precision) => utils_2.Utils.formatAmount(amount, precision),
81
- formatAssetAmount: (amount, symbol, precision) => utils_2.Utils.formatAssetAmount(amount, symbol, precision),
82
- calculatePercentageAmount: (amount, percentage, precision) => utils_2.Utils.calculatePercentageAmount(amount, percentage, precision),
83
- calculateBasisPointsAmount: (amount, basisPoints, precision) => utils_2.Utils.calculateBasisPointsAmount(amount, basisPoints, precision),
84
- splitAmountByBasisPoints: (amount, basisPoints, precision) => utils_2.Utils.splitAmountByBasisPoints(amount, basisPoints, precision),
85
- splitAmountByPercentage: (amount, percentages, precision) => utils_2.Utils.splitAmountByPercentage(amount, percentages, precision),
86
- splitAmountByWeights: (amount, weights, precision) => utils_2.Utils.splitAmountByWeights(amount, weights, precision),
94
+ parseAssetAmount: (rawAmount) => utils_1.Utils.parseAssetAmount(rawAmount),
95
+ formatAmount: (amount, precision) => utils_1.Utils.formatAmount(amount, precision),
96
+ formatAssetAmount: (amount, symbol, precision) => utils_1.Utils.formatAssetAmount(amount, symbol, precision),
97
+ calculatePercentageAmount: (amount, percentage, precision) => utils_1.Utils.calculatePercentageAmount(amount, percentage, precision),
98
+ calculateBasisPointsAmount: (amount, basisPoints, precision) => utils_1.Utils.calculateBasisPointsAmount(amount, basisPoints, precision),
99
+ splitAmountByBasisPoints: (amount, basisPoints, precision) => utils_1.Utils.splitAmountByBasisPoints(amount, basisPoints, precision),
100
+ splitAmountByPercentage: (amount, percentages, precision) => utils_1.Utils.splitAmountByPercentage(amount, percentages, precision),
101
+ splitAmountByWeights: (amount, weights, precision) => utils_1.Utils.splitAmountByWeights(amount, weights, precision),
87
102
  };
88
103
  flows = {
89
104
  incomingTransfers: (account) => new builders_1.IncomingTransfersBuilder(this, account),
@@ -107,6 +122,114 @@ class Streamer {
107
122
  removeProposals: () => new builders_1.HiveRemoveProposalsBuilder(this),
108
123
  upvote: () => new builders_1.HiveVoteBuilder(this, 'upvote'),
109
124
  downvote: () => new builders_1.HiveVoteBuilder(this, 'downvote'),
125
+ follow: () => new builders_1.HiveFollowBuilder(this, 'follow'),
126
+ unfollow: () => new builders_1.HiveFollowBuilder(this, 'unfollow'),
127
+ mute: () => new builders_1.HiveFollowBuilder(this, 'mute'),
128
+ reblog: () => new builders_1.HiveReblogBuilder(this),
129
+ powerUp: () => new builders_1.HivePowerUpBuilder(this),
130
+ powerDown: () => new builders_1.HivePowerDownBuilder(this),
131
+ cancelPowerDown: () => new builders_1.HivePowerDownBuilder(this, true),
132
+ delegate: () => new builders_1.HiveDelegateBuilder(this),
133
+ undelegate: () => new builders_1.HiveDelegateBuilder(this, true),
134
+ claimRewards: () => new builders_1.HiveClaimRewardsBuilder(this),
135
+ witnessVote: () => new builders_1.HiveWitnessVoteBuilder(this),
136
+ setProxy: () => new builders_1.HiveSetProxyBuilder(this),
137
+ clearProxy: () => new builders_1.HiveSetProxyBuilder(this, true),
138
+ updateProfile: () => new builders_1.HiveUpdateProfileBuilder(this),
139
+ transferToSavings: () => new builders_1.HiveSavingsTransferBuilder(this, 'to'),
140
+ transferFromSavings: () => new builders_1.HiveSavingsTransferBuilder(this, 'from'),
141
+ convert: () => new builders_1.HiveConvertBuilder(this),
142
+ collateralizedConvert: () => new builders_1.HiveCollateralizedConvertBuilder(this),
143
+ deleteComment: () => new builders_1.HiveDeleteCommentBuilder(this),
144
+ limitOrder: () => new builders_1.HiveLimitOrderBuilder(this),
145
+ cancelOrder: () => new builders_1.HiveCancelOrderBuilder(this),
146
+ withdrawRoute: () => new builders_1.HiveWithdrawRouteBuilder(this),
147
+ commentOptions: () => new builders_1.HiveCommentOptionsBuilder(this),
148
+ post: () => new builders_1.HivePostBuilder(this),
149
+ stakeEngine: () => new builders_1.HiveEngineStakeBuilder(this),
150
+ unstakeEngine: () => new builders_1.HiveEngineUnstakeBuilder(this),
151
+ buyEngine: () => new builders_1.HiveEngineMarketOrderBuilder(this, 'buy'),
152
+ sellEngine: () => new builders_1.HiveEngineMarketOrderBuilder(this, 'sell'),
153
+ cancelEngineOrder: () => new builders_1.HiveEngineCancelOrderBuilder(this),
154
+ delegateEngine: () => new builders_1.HiveEngineDelegateBuilder(this),
155
+ undelegateEngine: () => new builders_1.HiveEngineDelegateBuilder(this, true),
156
+ subscribeCommunity: () => new builders_1.HiveCommunityOperationBuilder(this, 'subscribe'),
157
+ unsubscribeCommunity: () => new builders_1.HiveCommunityOperationBuilder(this, 'unsubscribe'),
158
+ cancelRecurrentTransfer: () => new builders_1.HiveRecurrentTransferBuilder(this),
159
+ };
160
+ query = {
161
+ getDynamicGlobalProperties: () => this.client.database.getDynamicGlobalProperties(),
162
+ getChainProperties: () => this.client.database.getChainProperties(),
163
+ getCurrentMedianHistoryPrice: () => this.client.database.getCurrentMedianHistoryPrice(),
164
+ getRewardFund: (name = 'post') => this.client.database.call('get_reward_fund', [name]),
165
+ getFollowers: (account, start = '', type = 'blog', limit = 1000) => this.client.call('condenser_api', 'get_followers', [account, start, type, limit]),
166
+ getFollowing: (account, start = '', type = 'blog', limit = 1000) => this.client.call('condenser_api', 'get_following', [account, start, type, limit]),
167
+ getFollowCount: (account) => this.client.call('condenser_api', 'get_follow_count', [account]),
168
+ getContent: (author, permlink) => this.client.call('condenser_api', 'get_content', [author, permlink]),
169
+ getContentReplies: (author, permlink) => this.client.call('condenser_api', 'get_content_replies', [author, permlink]),
170
+ getDiscussions: (by, query) => this.client.database.getDiscussions(by, query),
171
+ getBlog: (account, options = {}) => this.client.database.getDiscussions('blog', { tag: account, limit: 20, ...options }),
172
+ getFeed: (account, options = {}) => this.client.database.getDiscussions('feed', { tag: account, limit: 20, ...options }),
173
+ getTrending: (options = {}) => this.client.database.getDiscussions('trending', { limit: 20, ...options }),
174
+ getHot: (options = {}) => this.client.database.getDiscussions('hot', { limit: 20, ...options }),
175
+ getCreated: (options = {}) => this.client.database.getDiscussions('created', { limit: 20, ...options }),
176
+ getActiveVotes: (author, permlink) => this.client.call('condenser_api', 'get_active_votes', [author, permlink]),
177
+ getVestingDelegations: (account, from = '', limit = 100) => this.client.database.getVestingDelegations(account, from, limit),
178
+ getAccountHistory: (account, from = -1, limit = 100) => this.client.database.getAccountHistory(account, from, limit),
179
+ getOrderBook: (limit = 50) => this.client.call('condenser_api', 'get_order_book', [limit]),
180
+ getOpenOrders: (account) => this.client.call('condenser_api', 'get_open_orders', [account]),
181
+ getRCMana: (account) => this.client.rc.getRCMana(account),
182
+ getVPMana: (account) => this.client.rc.getVPMana(account),
183
+ findRCAccounts: (accounts) => this.client.rc.findRCAccounts(accounts),
184
+ getCommunity: (name) => this.client.call('bridge', 'get_community', { name }),
185
+ listCommunities: (options = {}) => this.client.call('bridge', 'list_communities', { limit: 100, ...options }),
186
+ getAccountNotifications: (account, options = {}) => this.client.call('bridge', 'account_notifications', { account, limit: 50, ...options }),
187
+ listAllSubscriptions: (account) => this.client.call('bridge', 'list_all_subscriptions', { account }),
188
+ findTransaction: (transactionId) => this.client.transaction.findTransaction(transactionId),
189
+ getWitnessByAccount: (account) => this.client.call('condenser_api', 'get_witness_by_account', [account]),
190
+ getWitnesses: (ids) => this.client.call('condenser_api', 'get_witnesses', [ids]),
191
+ getWitnessesByVote: (from, limit) => this.client.call('condenser_api', 'get_witnesses_by_vote', [from, limit]),
192
+ getBlock: (blockNumber) => this.client.database.getBlock(blockNumber),
193
+ getBlockHeader: (blockNumber) => this.client.database.getBlockHeader(blockNumber),
194
+ getOperations: (blockNumber, onlyVirtual = false) => this.client.database.getOperations(blockNumber, onlyVirtual),
195
+ getConfig: () => this.client.database.getConfig(),
196
+ lookupAccounts: (lowerBound, limit) => this.client.call('condenser_api', 'lookup_accounts', [lowerBound, limit]),
197
+ lookupWitnessAccounts: (lowerBound, limit) => this.client.call('condenser_api', 'lookup_witness_accounts', [lowerBound, limit]),
198
+ getConversionRequests: (account) => this.client.call('condenser_api', 'get_conversion_requests', [account]),
199
+ getCollateralizedConversionRequests: (account) => this.client.call('condenser_api', 'get_collateralized_conversion_requests', [account]),
200
+ getSavingsWithdrawFrom: (account) => this.client.call('condenser_api', 'get_savings_withdraw_from', [account]),
201
+ getProposals: (options = {}) => this.client.call('condenser_api', 'list_proposals', [
202
+ options.start || '',
203
+ options.limit || 100,
204
+ options.order || 'by_total_votes',
205
+ options.order_direction || 'descending',
206
+ options.status || 'votable'
207
+ ]),
208
+ };
209
+ engine = {
210
+ getTokenBalances: (account) => this.hive.find('tokens', 'balances', { account }),
211
+ getTokenBalance: (account, symbol) => this.hive.findOne('tokens', 'balances', { account, symbol }),
212
+ getToken: (symbol) => this.hive.findOne('tokens', 'tokens', { symbol }),
213
+ getTokens: (query = {}, limit = 1000, offset = 0) => this.hive.find('tokens', 'tokens', query, limit, offset),
214
+ getMarketBuyBook: (symbol, limit = 100, offset = 0) => this.hive.find('market', 'buyBook', { symbol }, limit, offset, [{ index: 'priceDec', descending: true }]),
215
+ getMarketSellBook: (symbol, limit = 100, offset = 0) => this.hive.find('market', 'sellBook', { symbol }, limit, offset, [{ index: 'priceDec', descending: false }]),
216
+ getMarketHistory: (symbol, limit = 100, offset = 0) => this.hive.find('market', 'tradesHistory', { symbol }, limit, offset, [{ index: '_id', descending: true }]),
217
+ getMarketMetrics: (query = {}) => this.hive.find('market', 'metrics', query),
218
+ getNFT: (symbol) => this.hive.findOne('nft', 'nfts', { symbol }),
219
+ getNFTInstances: (symbol, query = {}, limit = 100, offset = 0) => this.hive.find('nft', `${symbol}instances`, query, limit, offset),
220
+ getNFTBalance: (account, symbol) => this.hive.find('nft', `${symbol}instances`, { account }),
221
+ getNFTSellBook: (symbol, limit = 100, offset = 0) => this.hive.find('nftmarket', `${symbol}sellBook`, {}, limit, offset),
222
+ getPendingUnstakes: (account, symbol) => {
223
+ const query = { account };
224
+ if (symbol) {
225
+ query.symbol = symbol;
226
+ }
227
+ return this.hive.find('tokens', 'pendingUnstakes', query);
228
+ },
229
+ getDelegations: (from, symbol) => this.hive.find('tokens', 'delegations', { from, symbol }),
230
+ getContractInfo: (name) => this.hive.getContractInfo(name),
231
+ find: (contract, table, query, limit = 1000, offset = 0) => this.hive.find(contract, table, query, limit, offset),
232
+ findOne: (contract, table, query) => this.hive.findOne(contract, table, query),
110
233
  };
111
234
  constructor(userConfig = {}) {
112
235
  this.config = (0, config_1.createConfig)(userConfig);
@@ -156,7 +279,7 @@ class Streamer {
156
279
  let amount = '';
157
280
  let asset = '';
158
281
  try {
159
- const parsed = utils_2.Utils.parseAssetAmount(rawAmount);
282
+ const parsed = utils_1.Utils.parseAssetAmount(rawAmount);
160
283
  amount = parsed.amount;
161
284
  asset = parsed.asset;
162
285
  }
@@ -214,6 +337,10 @@ class Streamer {
214
337
  has: (key) => store.has(key),
215
338
  add: (key) => {
216
339
  store.add(key);
340
+ if (store.size > 10000) {
341
+ const oldest = store.values().next().value;
342
+ store.delete(oldest);
343
+ }
217
344
  }
218
345
  };
219
346
  }
@@ -334,7 +461,7 @@ class Streamer {
334
461
  }
335
462
  if ('group' in route) {
336
463
  const weights = this.resolveGroupWeights(route, routeIndex);
337
- const amounts = utils_2.Utils.splitAmountByWeights(amount, weights);
464
+ const amounts = utils_1.Utils.splitAmountByWeights(amount, weights);
338
465
  return route.group.map((recipient, groupIndex) => {
339
466
  const destination = typeof recipient.account === 'function' ? recipient.account(event) : recipient.account;
340
467
  if (typeof destination !== 'string' || destination.trim().length === 0) {
@@ -373,7 +500,7 @@ class Streamer {
373
500
  if (!Array.isArray(routes) || routes.length === 0) {
374
501
  throw new Error('At least one flow route is required');
375
502
  }
376
- const parsed = utils_2.Utils.parseAssetAmount(event.transfer.rawAmount);
503
+ const parsed = utils_1.Utils.parseAssetAmount(event.transfer.rawAmount);
377
504
  if (Array.isArray(allowedSymbols) && allowedSymbols.length > 0 && !allowedSymbols.includes(parsed.asset)) {
378
505
  throw new Error(`Asset '${parsed.asset}' is not allowed for this flow`);
379
506
  }
@@ -387,11 +514,11 @@ class Streamer {
387
514
  let onTopRouteAmounts = [];
388
515
  if (onTopRoutes.length > 0) {
389
516
  const onTopAllocations = this.normalizeOnTopRouteAllocations(onTopRoutes);
390
- const pools = utils_2.Utils.splitAmountByWeights(parsed.value, [10000, ...onTopAllocations]);
517
+ const pools = utils_1.Utils.splitAmountByWeights(parsed.value, [10000, ...onTopAllocations]);
391
518
  baseAmount = pools[0];
392
519
  onTopRouteAmounts = pools.slice(1);
393
520
  }
394
- const baseRouteAmounts = utils_2.Utils.splitAmountByBasisPoints(baseAmount, baseAllocations);
521
+ const baseRouteAmounts = utils_1.Utils.splitAmountByBasisPoints(baseAmount, baseAllocations);
395
522
  const routesPlan = routes.flatMap((route, index) => {
396
523
  const memo = this.resolvePlannedRouteMemo(event, route, index, defaultMemo);
397
524
  const amount = this.resolveFlowMode(route) === 'base'
@@ -401,7 +528,7 @@ class Streamer {
401
528
  });
402
529
  const onTopPlannedRoutes = routesPlan.filter((route) => route.mode === 'onTop');
403
530
  return {
404
- incomingAmount: utils_2.Utils.formatAssetAmount(parsed.value, parsed.asset),
531
+ incomingAmount: utils_1.Utils.formatAssetAmount(parsed.value, parsed.asset),
405
532
  asset: parsed.asset,
406
533
  baseAmount,
407
534
  onTopAmount: this.sumPlannedRouteAmounts(onTopPlannedRoutes),
@@ -427,11 +554,11 @@ class Streamer {
427
554
  }
428
555
  calculateSingleFlowAmount(transfer, basisPoints, allowedSymbols, errorContext) {
429
556
  const rawAmount = typeof transfer === 'string' ? transfer : transfer?.amount || '';
430
- const parsed = utils_2.Utils.parseAssetAmount(rawAmount);
557
+ const parsed = utils_1.Utils.parseAssetAmount(rawAmount);
431
558
  if (Array.isArray(allowedSymbols) && allowedSymbols.length > 0 && !allowedSymbols.includes(parsed.asset)) {
432
559
  throw new Error(`Asset '${parsed.asset}' is not allowed for ${errorContext}`);
433
560
  }
434
- const amount = basisPoints === null ? parsed.amount : utils_2.Utils.calculateBasisPointsAmount(parsed.value, basisPoints);
561
+ const amount = basisPoints === null ? parsed.amount : utils_1.Utils.calculateBasisPointsAmount(parsed.value, basisPoints);
435
562
  if (amount === '0.000') {
436
563
  throw new Error('Route amount must be greater than zero');
437
564
  }
@@ -775,7 +902,7 @@ class Streamer {
775
902
  await this.blockProvider.destroy?.();
776
903
  this.adapterInitialized = false;
777
904
  this.adapterInitializationPromise = null;
778
- await (0, utils_1.sleep)(25);
905
+ await utils_1.Utils.sleep(25);
779
906
  }
780
907
  async startApiServer(port = this.config.API_PORT) {
781
908
  await this.ensureAdapterReady();
@@ -842,7 +969,7 @@ class Streamer {
842
969
  console.log(`Head block number: `, props.head_block_number);
843
970
  console.log(`Last block number: `, this.lastBlockNumber);
844
971
  }
845
- const BLOCKS_BEHIND = parseInt(this.config.BLOCKS_BEHIND_WARNING, 10);
972
+ const BLOCKS_BEHIND = this.config.BLOCKS_BEHIND_WARNING;
846
973
  const maxBatchSize = Math.max(1, this.config.CATCH_UP_BATCH_SIZE || 1);
847
974
  const blocksBehind = Math.max(0, props.head_block_number - this.lastBlockNumber);
848
975
  const blocksToProcess = Math.min(blocksBehind, maxBatchSize);
@@ -896,7 +1023,7 @@ class Streamer {
896
1023
  }
897
1024
  // The block doesn't exist, wait and try again
898
1025
  if (!block) {
899
- await utils_2.Utils.sleep(this.config.BLOCK_CHECK_INTERVAL);
1026
+ await utils_1.Utils.sleep(this.config.BLOCK_CHECK_INTERVAL);
900
1027
  return;
901
1028
  }
902
1029
  // Get the block date and time
@@ -908,11 +1035,15 @@ class Streamer {
908
1035
  }
909
1036
  this.blockId = block.block_id;
910
1037
  this.previousBlockId = block.previous;
911
- this.transactionId = block.transaction_ids[1];
1038
+ this.transactionId = block.transaction_ids[0];
912
1039
  this.blockTime = blockTime;
913
1040
  if (this.adapter?.processBlock) {
914
- this.adapter.processBlock(block);
1041
+ await this.adapter.processBlock(block);
915
1042
  }
1043
+ // Fire onBlock subscribers
1044
+ this.blockSubscriptions.forEach(sub => {
1045
+ sub.callback(block, this.lastBlockNumber);
1046
+ });
916
1047
  // Hive operations are order-sensitive, so process them sequentially.
917
1048
  const transactions = block.transactions;
918
1049
  const transactionIds = block.transaction_ids;
@@ -935,6 +1066,30 @@ class Streamer {
935
1066
  }
936
1067
  this.lastBlockNumber = blockNumber;
937
1068
  this.saveStateThrottled();
1069
+ this.cleanupCaches();
1070
+ }
1071
+ cleanupCaches() {
1072
+ const now = Date.now();
1073
+ if (now - this.lastCacheCleanup < 60000) {
1074
+ return;
1075
+ }
1076
+ this.lastCacheCleanup = now;
1077
+ if (this.blockCache.size > 100) {
1078
+ const entriesToRemove = this.blockCache.size - 100;
1079
+ const iterator = this.blockCache.keys();
1080
+ for (let i = 0; i < entriesToRemove; i++) {
1081
+ const key = iterator.next().value;
1082
+ this.blockCache.delete(key);
1083
+ }
1084
+ }
1085
+ for (const [key, value] of this.accountCache) {
1086
+ if (now - value.timestamp > this.cacheTimeout) {
1087
+ this.accountCache.delete(key);
1088
+ }
1089
+ }
1090
+ if (this.transactionCache.size > this.maxCacheSize) {
1091
+ this.transactionCache.clear();
1092
+ }
938
1093
  }
939
1094
  async processOperation(op, blockNumber, blockId, prevBlockId, trxId, blockTime) {
940
1095
  const operationType = op[0];
@@ -949,6 +1104,10 @@ class Streamer {
949
1104
  if (this.adapter?.processOperation) {
950
1105
  await this.adapter.processOperation(op, blockNumber, blockId, prevBlockId, trxId, blockTime);
951
1106
  }
1107
+ // Fire onAnyOperation subscribers
1108
+ this.anyOperationSubscriptions.forEach(sub => {
1109
+ sub.callback(op, blockNumber, blockId, prevBlockId, trxId, blockTime);
1110
+ });
952
1111
  // Operation is a "comment" which could either be a post or comment
953
1112
  if (operationType === 'comment') {
954
1113
  // This is a post
@@ -971,7 +1130,7 @@ class Streamer {
971
1130
  let amount = '';
972
1131
  let asset = '';
973
1132
  try {
974
- const parsedAmount = utils_2.Utils.parseAssetAmount(String(rawAmount || ''));
1133
+ const parsedAmount = utils_1.Utils.parseAssetAmount(String(rawAmount || ''));
975
1134
  amount = parsedAmount.amount;
976
1135
  asset = parsedAmount.asset;
977
1136
  }
@@ -987,7 +1146,7 @@ class Streamer {
987
1146
  asset,
988
1147
  memo: operationData?.memo
989
1148
  };
990
- const json = utils_2.Utils.jsonParse(operationData.memo);
1149
+ const json = utils_1.Utils.jsonParse(operationData.memo);
991
1150
  const payload = this.normalizeContractPayload(json?.[this.config.PAYLOAD_IDENTIFIER]);
992
1151
  if (payload) {
993
1152
  if (this?.adapter?.processTransfer) {
@@ -1024,7 +1183,7 @@ class Streamer {
1024
1183
  sender = operationData.required_posting_auths[0];
1025
1184
  isSignedWithActiveKey = false;
1026
1185
  }
1027
- const json = utils_2.Utils.jsonParse(operationData.json);
1186
+ const json = utils_1.Utils.jsonParse(operationData.json);
1028
1187
  const payload = id === this.config.JSON_ID
1029
1188
  ? this.normalizeContractPayload(json?.[this.config.PAYLOAD_IDENTIFIER])
1030
1189
  : null;
@@ -1064,7 +1223,7 @@ class Streamer {
1064
1223
  let hasVerificationErrors = false;
1065
1224
  try {
1066
1225
  const txInfo = await this.hive.getTransactionInfo(trxId);
1067
- const logs = txInfo && txInfo.logs ? utils_2.Utils.jsonParse(txInfo.logs) : null;
1226
+ const logs = txInfo && txInfo.logs ? utils_1.Utils.jsonParse(txInfo.logs) : null;
1068
1227
  hasVerificationErrors = Boolean(txInfo && logs && typeof logs.errors !== 'undefined');
1069
1228
  }
1070
1229
  catch (e) {
@@ -1080,7 +1239,7 @@ class Streamer {
1080
1239
  // Recurrent transfers carry payloads in memo, similar to transfer.
1081
1240
  if (operationType === 'recurrent_transfer') {
1082
1241
  const sender = operationData?.from;
1083
- const json = utils_2.Utils.jsonParse(operationData?.memo);
1242
+ const json = utils_1.Utils.jsonParse(operationData?.memo);
1084
1243
  const payload = this.normalizeContractPayload(json?.[this.config.PAYLOAD_IDENTIFIER]);
1085
1244
  if (payload) {
1086
1245
  const context = this.buildContractContext('recurrent_transfer', blockNumber, blockId, prevBlockId, trxId, blockTime, {
@@ -1100,7 +1259,7 @@ class Streamer {
1100
1259
  await this.adapter.processEscrow(operationType, operationData, operationMetadata);
1101
1260
  }
1102
1261
  if (operationType === 'escrow_transfer') {
1103
- const jsonMeta = utils_2.Utils.jsonParse(operationData?.json_meta);
1262
+ const jsonMeta = utils_1.Utils.jsonParse(operationData?.json_meta);
1104
1263
  const payload = this.normalizeContractPayload(jsonMeta?.[this.config.PAYLOAD_IDENTIFIER]);
1105
1264
  if (payload) {
1106
1265
  const context = this.buildContractContext('escrow_transfer', blockNumber, blockId, prevBlockId, trxId, blockTime, {
@@ -1120,6 +1279,89 @@ class Streamer {
1120
1279
  }
1121
1280
  });
1122
1281
  }
1282
+ // Vote operations
1283
+ if (operationType === 'vote') {
1284
+ this.voteSubscriptions.forEach(sub => {
1285
+ sub.callback(operationData, blockNumber, blockId, prevBlockId, trxId, blockTime);
1286
+ });
1287
+ }
1288
+ // Delegation operations
1289
+ if (operationType === 'delegate_vesting_shares') {
1290
+ this.delegateSubscriptions.forEach(sub => {
1291
+ sub.callback(operationData, blockNumber, blockId, prevBlockId, trxId, blockTime);
1292
+ });
1293
+ }
1294
+ // Power up (transfer_to_vesting)
1295
+ if (operationType === 'transfer_to_vesting') {
1296
+ this.powerUpSubscriptions.forEach(sub => {
1297
+ sub.callback(operationData, blockNumber, blockId, prevBlockId, trxId, blockTime);
1298
+ });
1299
+ }
1300
+ // Power down (withdraw_vesting)
1301
+ if (operationType === 'withdraw_vesting') {
1302
+ this.powerDownSubscriptions.forEach(sub => {
1303
+ sub.callback(operationData, blockNumber, blockId, prevBlockId, trxId, blockTime);
1304
+ });
1305
+ }
1306
+ // Claim reward balance
1307
+ if (operationType === 'claim_reward_balance') {
1308
+ this.claimRewardsSubscriptions.forEach(sub => {
1309
+ sub.callback(operationData, blockNumber, blockId, prevBlockId, trxId, blockTime);
1310
+ });
1311
+ }
1312
+ // Witness vote
1313
+ if (operationType === 'account_witness_vote') {
1314
+ this.witnessVoteSubscriptions.forEach(sub => {
1315
+ sub.callback(operationData, blockNumber, blockId, prevBlockId, trxId, blockTime);
1316
+ });
1317
+ }
1318
+ // Follow/unfollow/mute/reblog via custom_json with id 'follow'
1319
+ if (operationType === 'custom_json' && operationData?.id === 'follow') {
1320
+ const json = utils_1.Utils.jsonParse(operationData.json);
1321
+ if (Array.isArray(json) && json.length === 2) {
1322
+ const [type, payload] = json;
1323
+ if (type === 'follow' && payload && (this.followSubscriptions.length > 0)) {
1324
+ this.followSubscriptions.forEach(sub => {
1325
+ sub.callback(payload, blockNumber, blockId, prevBlockId, trxId, blockTime);
1326
+ });
1327
+ }
1328
+ if (type === 'reblog' && payload && (this.reblogSubscriptions.length > 0)) {
1329
+ this.reblogSubscriptions.forEach(sub => {
1330
+ sub.callback(payload, blockNumber, blockId, prevBlockId, trxId, blockTime);
1331
+ });
1332
+ }
1333
+ }
1334
+ }
1335
+ // Account updates
1336
+ if (operationType === 'account_update' || operationType === 'account_update2') {
1337
+ this.accountUpdateSubscriptions.forEach(sub => {
1338
+ sub.callback(operationData, blockNumber, blockId, prevBlockId, trxId, blockTime);
1339
+ });
1340
+ }
1341
+ // Delete comment
1342
+ if (operationType === 'delete_comment') {
1343
+ this.deleteCommentSubscriptions.forEach(sub => {
1344
+ sub.callback(operationData, blockNumber, blockId, prevBlockId, trxId, blockTime);
1345
+ });
1346
+ }
1347
+ // Limit orders
1348
+ if (operationType === 'limit_order_create' || operationType === 'limit_order_create2' || operationType === 'limit_order_cancel') {
1349
+ this.limitOrderSubscriptions.forEach(sub => {
1350
+ sub.callback(operationData, blockNumber, blockId, prevBlockId, trxId, blockTime);
1351
+ });
1352
+ }
1353
+ // Savings transfers
1354
+ if (operationType === 'transfer_to_savings' || operationType === 'transfer_from_savings' || operationType === 'cancel_transfer_from_savings') {
1355
+ this.savingsSubscriptions.forEach(sub => {
1356
+ sub.callback(operationData, blockNumber, blockId, prevBlockId, trxId, blockTime);
1357
+ });
1358
+ }
1359
+ // Convert operations
1360
+ if (operationType === 'convert' || operationType === 'collateralized_convert') {
1361
+ this.convertSubscriptions.forEach(sub => {
1362
+ sub.callback(operationData, blockNumber, blockId, prevBlockId, trxId, blockTime);
1363
+ });
1364
+ }
1123
1365
  }
1124
1366
  normalizeContractPayload(payload) {
1125
1367
  if (!payload || typeof payload !== 'object') {
@@ -1358,24 +1600,24 @@ class Streamer {
1358
1600
  }
1359
1601
  }
1360
1602
  saveToHiveApi(from, data) {
1361
- return utils_2.Utils.transferHiveTokens(this.client, this.config, from, 'hiveapi', '0.001', 'HIVE', data);
1603
+ return utils_1.Utils.transferHiveTokens(this.client, this.config, from, 'hiveapi', '0.001', 'HIVE', data);
1362
1604
  }
1363
1605
  getAccountTransfers(account, from = -1, limit = 100) {
1364
- return utils_2.Utils.getAccountTransfers(this.client, account, from, limit);
1606
+ return utils_1.Utils.getAccountTransfers(this.client, account, from, limit);
1365
1607
  }
1366
1608
  transferHiveTokens(from, to, amount, symbol, memo = '') {
1367
- return utils_2.Utils.transferHiveTokens(this.client, this.config, from, to, amount, symbol, memo);
1609
+ return utils_1.Utils.transferHiveTokens(this.client, this.config, from, to, amount, symbol, memo);
1368
1610
  }
1369
1611
  burnHiveTokens(from, amount, symbol, memo = '') {
1370
- return utils_2.Utils.burnHiveTokens(this.client, this.config, from, amount, symbol, memo);
1612
+ return utils_1.Utils.burnHiveTokens(this.client, this.config, from, amount, symbol, memo);
1371
1613
  }
1372
1614
  burnTransferPortion(from, transfer, basisPoints, memo = '', allowedSymbols = ['HIVE', 'HBD']) {
1373
1615
  const rawAmount = typeof transfer === 'string' ? transfer : transfer?.amount || '';
1374
- const parsed = utils_2.Utils.parseAssetAmount(rawAmount);
1616
+ const parsed = utils_1.Utils.parseAssetAmount(rawAmount);
1375
1617
  if (Array.isArray(allowedSymbols) && allowedSymbols.length > 0 && !allowedSymbols.includes(parsed.asset)) {
1376
1618
  throw new Error(`Asset '${parsed.asset}' is not allowed for burn`);
1377
1619
  }
1378
- const burnAmount = utils_2.Utils.calculateBasisPointsAmount(parsed.value, basisPoints);
1620
+ const burnAmount = utils_1.Utils.calculateBasisPointsAmount(parsed.value, basisPoints);
1379
1621
  if (burnAmount === '0.000') {
1380
1622
  throw new Error('Burn amount must be greater than zero');
1381
1623
  }
@@ -1383,11 +1625,11 @@ class Streamer {
1383
1625
  }
1384
1626
  burnTransferPercentage(from, transfer, percentage, memo = '', allowedSymbols = ['HIVE', 'HBD']) {
1385
1627
  const rawAmount = typeof transfer === 'string' ? transfer : transfer?.amount || '';
1386
- const parsed = utils_2.Utils.parseAssetAmount(rawAmount);
1628
+ const parsed = utils_1.Utils.parseAssetAmount(rawAmount);
1387
1629
  if (Array.isArray(allowedSymbols) && allowedSymbols.length > 0 && !allowedSymbols.includes(parsed.asset)) {
1388
1630
  throw new Error(`Asset '${parsed.asset}' is not allowed for burn`);
1389
1631
  }
1390
- const burnAmount = utils_2.Utils.calculatePercentageAmount(parsed.value, percentage);
1632
+ const burnAmount = utils_1.Utils.calculatePercentageAmount(parsed.value, percentage);
1391
1633
  if (burnAmount === '0.000') {
1392
1634
  throw new Error('Burn amount must be greater than zero');
1393
1635
  }
@@ -1590,67 +1832,85 @@ class Streamer {
1590
1832
  };
1591
1833
  }
1592
1834
  transferHiveTokensMultiple(from, accounts = [], amount = '0', symbol, memo = '') {
1593
- return utils_2.Utils.transferHiveTokensMultiple(this.client, this.config, from, accounts, amount, symbol, memo);
1835
+ return utils_1.Utils.transferHiveTokensMultiple(this.client, this.config, from, accounts, amount, symbol, memo);
1594
1836
  }
1595
1837
  broadcastOperations(operations, signingKeys) {
1596
- return utils_2.Utils.broadcastOperations(this.client, operations, signingKeys || this.config.ACTIVE_KEY);
1838
+ if (signingKeys) {
1839
+ return utils_1.Utils.broadcastOperations(this.client, operations, signingKeys);
1840
+ }
1841
+ // Auto-detect key: use posting key for posting-level ops, active key for active-level ops
1842
+ const activeOps = new Set([
1843
+ 'transfer', 'transfer_to_vesting', 'withdraw_vesting', 'delegate_vesting_shares',
1844
+ 'transfer_to_savings', 'transfer_from_savings', 'cancel_transfer_from_savings',
1845
+ 'convert', 'collateralized_convert', 'limit_order_create', 'limit_order_create2',
1846
+ 'limit_order_cancel', 'escrow_transfer', 'escrow_approve', 'escrow_dispute',
1847
+ 'escrow_release', 'account_update', 'account_witness_vote', 'account_witness_proxy',
1848
+ 'set_withdraw_vesting_route', 'claim_account', 'create_claimed_account',
1849
+ 'create_proposal', 'update_proposal_votes', 'remove_proposal', 'recurrent_transfer',
1850
+ 'feed_publish'
1851
+ ]);
1852
+ const needsActive = operations.some(([opType]) => activeOps.has(opType));
1853
+ const key = needsActive
1854
+ ? (this.config.ACTIVE_KEY || this.config.POSTING_KEY)
1855
+ : (this.config.POSTING_KEY || this.config.ACTIVE_KEY);
1856
+ return utils_1.Utils.broadcastOperations(this.client, operations, key);
1597
1857
  }
1598
1858
  broadcastMultiSigOperations(operations, signingKeys) {
1599
- return utils_2.Utils.broadcastMultiSigOperations(this.client, operations, signingKeys);
1859
+ return utils_1.Utils.broadcastMultiSigOperations(this.client, operations, signingKeys);
1600
1860
  }
1601
1861
  createAuthority(keyAuths = [], accountAuths = [], weightThreshold = 1) {
1602
- return utils_2.Utils.createAuthority(keyAuths, accountAuths, weightThreshold);
1862
+ return utils_1.Utils.createAuthority(keyAuths, accountAuths, weightThreshold);
1603
1863
  }
1604
1864
  updateAccountAuthorities(account, authorityUpdate, signingKeys) {
1605
- return utils_2.Utils.updateAccountAuthorities(this.client, this.config, account, authorityUpdate, signingKeys);
1865
+ return utils_1.Utils.updateAccountAuthorities(this.client, this.config, account, authorityUpdate, signingKeys);
1606
1866
  }
1607
1867
  escrowTransfer(options, signingKeys) {
1608
- return utils_2.Utils.escrowTransfer(this.client, this.config, options, signingKeys);
1868
+ return utils_1.Utils.escrowTransfer(this.client, this.config, options, signingKeys);
1609
1869
  }
1610
1870
  escrowApprove(options, signingKeys) {
1611
- return utils_2.Utils.escrowApprove(this.client, this.config, options, signingKeys);
1871
+ return utils_1.Utils.escrowApprove(this.client, this.config, options, signingKeys);
1612
1872
  }
1613
1873
  escrowDispute(options, signingKeys) {
1614
- return utils_2.Utils.escrowDispute(this.client, this.config, options, signingKeys);
1874
+ return utils_1.Utils.escrowDispute(this.client, this.config, options, signingKeys);
1615
1875
  }
1616
1876
  escrowRelease(options, signingKeys) {
1617
- return utils_2.Utils.escrowRelease(this.client, this.config, options, signingKeys);
1877
+ return utils_1.Utils.escrowRelease(this.client, this.config, options, signingKeys);
1618
1878
  }
1619
1879
  recurrentTransfer(options, signingKeys) {
1620
- return utils_2.Utils.recurrentTransfer(this.client, this.config, options, signingKeys);
1880
+ return utils_1.Utils.recurrentTransfer(this.client, this.config, options, signingKeys);
1621
1881
  }
1622
1882
  createProposal(options, signingKeys) {
1623
- return utils_2.Utils.createProposal(this.client, this.config, options, signingKeys);
1883
+ return utils_1.Utils.createProposal(this.client, this.config, options, signingKeys);
1624
1884
  }
1625
1885
  updateProposalVotes(options, signingKeys) {
1626
- return utils_2.Utils.updateProposalVotes(this.client, this.config, options, signingKeys);
1886
+ return utils_1.Utils.updateProposalVotes(this.client, this.config, options, signingKeys);
1627
1887
  }
1628
1888
  removeProposals(options, signingKeys) {
1629
- return utils_2.Utils.removeProposals(this.client, this.config, options, signingKeys);
1889
+ return utils_1.Utils.removeProposals(this.client, this.config, options, signingKeys);
1630
1890
  }
1631
1891
  transferHiveEngineTokens(from, to, symbol, quantity, memo = '') {
1632
- return utils_2.Utils.transferHiveEngineTokens(this.client, this.config, from, to, quantity, symbol, memo);
1892
+ return utils_1.Utils.transferHiveEngineTokens(this.client, this.config, from, to, quantity, symbol, memo);
1633
1893
  }
1634
1894
  burnHiveEngineTokens(from, symbol, quantity, memo = '') {
1635
- return utils_2.Utils.burnHiveEngineTokens(this.client, this.config, from, symbol, quantity, memo);
1895
+ return utils_1.Utils.burnHiveEngineTokens(this.client, this.config, from, symbol, quantity, memo);
1636
1896
  }
1637
1897
  transferHiveEngineTokensMultiple(from, accounts = [], symbol, memo = '', amount = '0') {
1638
- return utils_2.Utils.transferHiveEngineTokensMultiple(this.client, this.config, from, accounts, symbol, memo, amount);
1898
+ return utils_1.Utils.transferHiveEngineTokensMultiple(this.client, this.config, from, accounts, symbol, memo, amount);
1639
1899
  }
1640
1900
  issueHiveEngineTokens(from, to, symbol, quantity, memo = '') {
1641
- return utils_2.Utils.issueHiveEngineTokens(this.client, this.config, from, to, symbol, quantity, memo);
1901
+ return utils_1.Utils.issueHiveEngineTokens(this.client, this.config, from, to, symbol, quantity, memo);
1642
1902
  }
1643
1903
  issueHiveEngineTokensMultiple(from, accounts = [], symbol, memo = '', amount = '0') {
1644
- return utils_2.Utils.issueHiveEngineTokensMultiple(this.client, this.config, from, accounts, symbol, memo, amount);
1904
+ return utils_1.Utils.issueHiveEngineTokensMultiple(this.client, this.config, from, accounts, symbol, memo, amount);
1645
1905
  }
1646
1906
  upvote(votePercentage = '100.0', username, permlink) {
1647
- return utils_2.Utils.upvote(this.client, this.config, this.username, votePercentage, username, permlink);
1907
+ return utils_1.Utils.upvote(this.client, this.config, this.username, votePercentage, username, permlink);
1648
1908
  }
1649
1909
  downvote(votePercentage = '100.0', username, permlink) {
1650
- return utils_2.Utils.downvote(this.client, this.config, this.username, votePercentage, username, permlink);
1910
+ return utils_1.Utils.downvote(this.client, this.config, this.username, votePercentage, username, permlink);
1651
1911
  }
1652
1912
  getTransaction(blockNumber, transactionId) {
1653
- return utils_2.Utils.getTransaction(this.client, blockNumber, transactionId);
1913
+ return utils_1.Utils.getTransaction(this.client, blockNumber, transactionId);
1654
1914
  }
1655
1915
  getStatus() {
1656
1916
  return {
@@ -1664,7 +1924,7 @@ class Streamer {
1664
1924
  };
1665
1925
  }
1666
1926
  verifyTransfer(transaction, from, to, amount) {
1667
- return utils_2.Utils.verifyTransfer(transaction, from, to, amount);
1927
+ return utils_1.Utils.verifyTransfer(transaction, from, to, amount);
1668
1928
  }
1669
1929
  onComment(callback) {
1670
1930
  this.commentSubscriptions.push({
@@ -1685,7 +1945,7 @@ class Streamer {
1685
1945
  onCustomJson(callback) {
1686
1946
  this.customJsonSubscriptions.push({ callback });
1687
1947
  }
1688
- onCustomJsonId(callback, id) {
1948
+ onCustomJsonId(id, callback) {
1689
1949
  this.customJsonIdSubscriptions.push({ callback, id });
1690
1950
  }
1691
1951
  onHiveEngine(callback) {
@@ -1703,6 +1963,189 @@ class Streamer {
1703
1963
  onEscrowRelease(callback) {
1704
1964
  this.escrowSubscriptions.push({ type: 'escrow_release', callback });
1705
1965
  }
1966
+ // ─── New Event Subscriptions ────────────────────────────────────────
1967
+ onVote(callback) {
1968
+ this.voteSubscriptions.push({ callback });
1969
+ }
1970
+ onDelegate(callback) {
1971
+ this.delegateSubscriptions.push({ callback });
1972
+ }
1973
+ onPowerUp(callback) {
1974
+ this.powerUpSubscriptions.push({ callback });
1975
+ }
1976
+ onPowerDown(callback) {
1977
+ this.powerDownSubscriptions.push({ callback });
1978
+ }
1979
+ onClaimRewards(callback) {
1980
+ this.claimRewardsSubscriptions.push({ callback });
1981
+ }
1982
+ onAccountWitnessVote(callback) {
1983
+ this.witnessVoteSubscriptions.push({ callback });
1984
+ }
1985
+ // ─── Social Operations ──────────────────────────────────────────────
1986
+ follow(follower, following) {
1987
+ return utils_1.Utils.follow(this.client, this.config, follower, following);
1988
+ }
1989
+ unfollow(follower, following) {
1990
+ return utils_1.Utils.unfollow(this.client, this.config, follower, following);
1991
+ }
1992
+ mute(follower, following) {
1993
+ return utils_1.Utils.mute(this.client, this.config, follower, following);
1994
+ }
1995
+ reblog(account, author, permlink) {
1996
+ return utils_1.Utils.reblog(this.client, this.config, account, author, permlink);
1997
+ }
1998
+ // ─── Staking Operations ─────────────────────────────────────────────
1999
+ powerUp(from, to, amount) {
2000
+ return utils_1.Utils.powerUp(this.client, this.config, from, to, amount);
2001
+ }
2002
+ powerDown(account, vestingShares) {
2003
+ return utils_1.Utils.powerDown(this.client, this.config, account, vestingShares);
2004
+ }
2005
+ cancelPowerDown(account) {
2006
+ return utils_1.Utils.cancelPowerDown(this.client, this.config, account);
2007
+ }
2008
+ delegateVestingShares(delegator, delegatee, vestingShares) {
2009
+ return utils_1.Utils.delegateVestingShares(this.client, this.config, delegator, delegatee, vestingShares);
2010
+ }
2011
+ undelegateVestingShares(delegator, delegatee) {
2012
+ return utils_1.Utils.undelegateVestingShares(this.client, this.config, delegator, delegatee);
2013
+ }
2014
+ // ─── Account Operations ─────────────────────────────────────────────
2015
+ claimRewards(account, rewardHive, rewardHbd, rewardVests) {
2016
+ return utils_1.Utils.claimRewards(this.client, this.config, account, rewardHive, rewardHbd, rewardVests);
2017
+ }
2018
+ witnessVote(account, witness, approve = true) {
2019
+ return utils_1.Utils.witnessVote(this.client, this.config, account, witness, approve);
2020
+ }
2021
+ setProxy(account, proxy) {
2022
+ return utils_1.Utils.setProxy(this.client, this.config, account, proxy);
2023
+ }
2024
+ clearProxy(account) {
2025
+ return utils_1.Utils.clearProxy(this.client, this.config, account);
2026
+ }
2027
+ updateProfile(account, profile) {
2028
+ return utils_1.Utils.updateProfile(this.client, this.config, account, profile);
2029
+ }
2030
+ getAccount(username) {
2031
+ return utils_1.Utils.getAccount(this.client, username);
2032
+ }
2033
+ getAccounts(usernames) {
2034
+ return utils_1.Utils.getAccounts(this.client, usernames);
2035
+ }
2036
+ // ─── Savings Operations ─────────────────────────────────────────────
2037
+ transferToSavings(from, to, amount, symbol, memo = '') {
2038
+ return utils_1.Utils.transferToSavings(this.client, this.config, from, to, amount, symbol, memo);
2039
+ }
2040
+ transferFromSavings(from, to, amount, symbol, requestId = 0, memo = '') {
2041
+ return utils_1.Utils.transferFromSavings(this.client, this.config, from, to, amount, symbol, requestId, memo);
2042
+ }
2043
+ cancelTransferFromSavings(from, requestId) {
2044
+ return utils_1.Utils.cancelTransferFromSavings(this.client, this.config, from, requestId);
2045
+ }
2046
+ // ─── Convert Operations ─────────────────────────────────────────────
2047
+ convert(owner, amount, requestId = 0) {
2048
+ return utils_1.Utils.convert(this.client, this.config, owner, amount, requestId);
2049
+ }
2050
+ collateralizedConvert(owner, amount, requestId = 0) {
2051
+ return utils_1.Utils.collateralizedConvert(this.client, this.config, owner, amount, requestId);
2052
+ }
2053
+ // ─── Content Operations ─────────────────────────────────────────────
2054
+ deleteComment(author, permlink) {
2055
+ return utils_1.Utils.deleteComment(this.client, this.config, author, permlink);
2056
+ }
2057
+ commentOptions(author, permlink, options) {
2058
+ return utils_1.Utils.commentOptions(this.client, this.config, author, permlink, options);
2059
+ }
2060
+ // ─── Market Operations ──────────────────────────────────────────────
2061
+ limitOrderCreate(owner, orderId, amountToSell, minToReceive, fillOrKill = false, expiration, signingKeys) {
2062
+ return utils_1.Utils.limitOrderCreate(this.client, this.config, owner, orderId, amountToSell, minToReceive, fillOrKill, expiration);
2063
+ }
2064
+ limitOrderCancel(owner, orderId, signingKeys) {
2065
+ return utils_1.Utils.limitOrderCancel(this.client, this.config, owner, orderId);
2066
+ }
2067
+ // ─── Vesting Route ──────────────────────────────────────────────────
2068
+ setWithdrawVestingRoute(fromAccount, toAccount, percent, autoVest = false, signingKeys) {
2069
+ return utils_1.Utils.setWithdrawVestingRoute(this.client, this.config, fromAccount, toAccount, percent, autoVest, signingKeys);
2070
+ }
2071
+ // ─── Account Creation ───────────────────────────────────────────────
2072
+ claimAccount(creator, fee = '0.000 HIVE') {
2073
+ return utils_1.Utils.claimAccount(this.client, this.config, creator, fee);
2074
+ }
2075
+ feedPublish(publisher, baseAmount, quoteAmount = '1.000 HIVE') {
2076
+ return utils_1.Utils.feedPublish(this.client, this.config, publisher, baseAmount, quoteAmount);
2077
+ }
2078
+ // ─── Batch Builder ────────────────────────────────────────────────
2079
+ batch() {
2080
+ return new builders_1.HiveBatchBuilder(this);
2081
+ }
2082
+ // ─── Authority Management ───────────────────────────────────────────
2083
+ hasPostingAuth(account, authAccount) {
2084
+ return utils_1.Utils.hasPostingAuth(this.client, account, authAccount);
2085
+ }
2086
+ grantPostingAuth(account, authAccount, signingKeys) {
2087
+ return utils_1.Utils.grantPostingAuth(this.client, this.config, account, authAccount, signingKeys);
2088
+ }
2089
+ revokePostingAuth(account, authAccount, signingKeys) {
2090
+ return utils_1.Utils.revokePostingAuth(this.client, this.config, account, authAccount, signingKeys);
2091
+ }
2092
+ // ─── Additional Event Subscriptions ─────────────────────────────────
2093
+ onFollow(callback) {
2094
+ this.followSubscriptions.push({ callback });
2095
+ }
2096
+ onReblog(callback) {
2097
+ this.reblogSubscriptions.push({ callback });
2098
+ }
2099
+ onAccountUpdate(callback) {
2100
+ this.accountUpdateSubscriptions.push({ callback });
2101
+ }
2102
+ onDeleteComment(callback) {
2103
+ this.deleteCommentSubscriptions.push({ callback });
2104
+ }
2105
+ onLimitOrder(callback) {
2106
+ this.limitOrderSubscriptions.push({ callback });
2107
+ }
2108
+ onSavingsTransfer(callback) {
2109
+ this.savingsSubscriptions.push({ callback });
2110
+ }
2111
+ onConvert(callback) {
2112
+ this.convertSubscriptions.push({ callback });
2113
+ }
2114
+ onBlock(callback) {
2115
+ this.blockSubscriptions.push({ callback });
2116
+ }
2117
+ onAnyOperation(callback) {
2118
+ this.anyOperationSubscriptions.push({ callback });
2119
+ }
2120
+ // ─── Hive Engine Write Operations ───────────────────────────────────
2121
+ stakeEngineTokens(from, to, symbol, quantity) {
2122
+ return utils_1.Utils.stakeEngineTokens(this.client, this.config, from, to, symbol, quantity);
2123
+ }
2124
+ unstakeEngineTokens(from, symbol, quantity) {
2125
+ return utils_1.Utils.unstakeEngineTokens(this.client, this.config, from, symbol, quantity);
2126
+ }
2127
+ buyEngineTokens(from, symbol, quantity, price) {
2128
+ return utils_1.Utils.buyEngineTokens(this.client, this.config, from, symbol, quantity, price);
2129
+ }
2130
+ sellEngineTokens(from, symbol, quantity, price) {
2131
+ return utils_1.Utils.sellEngineTokens(this.client, this.config, from, symbol, quantity, price);
2132
+ }
2133
+ cancelEngineOrder(from, type, orderId) {
2134
+ return utils_1.Utils.cancelEngineOrder(this.client, this.config, from, type, orderId);
2135
+ }
2136
+ delegateEngineTokens(from, to, symbol, quantity) {
2137
+ return utils_1.Utils.delegateEngineTokens(this.client, this.config, from, to, symbol, quantity);
2138
+ }
2139
+ undelegateEngineTokens(from, to, symbol, quantity) {
2140
+ return utils_1.Utils.undelegateEngineTokens(this.client, this.config, from, to, symbol, quantity);
2141
+ }
2142
+ // ─── Community Operations ───────────────────────────────────────────
2143
+ subscribeCommunity(account, community) {
2144
+ return utils_1.Utils.subscribeCommunity(this.client, this.config, account, community);
2145
+ }
2146
+ unsubscribeCommunity(account, community) {
2147
+ return utils_1.Utils.unsubscribeCommunity(this.client, this.config, account, community);
2148
+ }
1706
2149
  // Memory management: cleanup subscriptions
1707
2150
  cleanupSubscriptions() {
1708
2151
  // Limit subscription arrays to prevent memory leaks
@@ -1734,6 +2177,41 @@ class Streamer {
1734
2177
  this.escrowSubscriptions = this.escrowSubscriptions.slice(-this.maxSubscriptions);
1735
2178
  console.warn(`[Streamer] Trimmed escrowSubscriptions to ${this.maxSubscriptions} items`);
1736
2179
  }
2180
+ if (this.voteSubscriptions.length > this.maxSubscriptions) {
2181
+ this.voteSubscriptions = this.voteSubscriptions.slice(-this.maxSubscriptions);
2182
+ console.warn(`[Streamer] Trimmed voteSubscriptions to ${this.maxSubscriptions} items`);
2183
+ }
2184
+ if (this.delegateSubscriptions.length > this.maxSubscriptions) {
2185
+ this.delegateSubscriptions = this.delegateSubscriptions.slice(-this.maxSubscriptions);
2186
+ console.warn(`[Streamer] Trimmed delegateSubscriptions to ${this.maxSubscriptions} items`);
2187
+ }
2188
+ if (this.powerUpSubscriptions.length > this.maxSubscriptions) {
2189
+ this.powerUpSubscriptions = this.powerUpSubscriptions.slice(-this.maxSubscriptions);
2190
+ console.warn(`[Streamer] Trimmed powerUpSubscriptions to ${this.maxSubscriptions} items`);
2191
+ }
2192
+ if (this.powerDownSubscriptions.length > this.maxSubscriptions) {
2193
+ this.powerDownSubscriptions = this.powerDownSubscriptions.slice(-this.maxSubscriptions);
2194
+ console.warn(`[Streamer] Trimmed powerDownSubscriptions to ${this.maxSubscriptions} items`);
2195
+ }
2196
+ if (this.claimRewardsSubscriptions.length > this.maxSubscriptions) {
2197
+ this.claimRewardsSubscriptions = this.claimRewardsSubscriptions.slice(-this.maxSubscriptions);
2198
+ console.warn(`[Streamer] Trimmed claimRewardsSubscriptions to ${this.maxSubscriptions} items`);
2199
+ }
2200
+ if (this.witnessVoteSubscriptions.length > this.maxSubscriptions) {
2201
+ this.witnessVoteSubscriptions = this.witnessVoteSubscriptions.slice(-this.maxSubscriptions);
2202
+ console.warn(`[Streamer] Trimmed witnessVoteSubscriptions to ${this.maxSubscriptions} items`);
2203
+ }
2204
+ const extraArrays = [
2205
+ 'followSubscriptions', 'reblogSubscriptions', 'accountUpdateSubscriptions',
2206
+ 'deleteCommentSubscriptions', 'limitOrderSubscriptions', 'savingsSubscriptions',
2207
+ 'convertSubscriptions'
2208
+ ];
2209
+ for (const name of extraArrays) {
2210
+ if (this[name].length > this.maxSubscriptions) {
2211
+ this[name] = this[name].slice(-this.maxSubscriptions);
2212
+ console.warn(`[Streamer] Trimmed ${name} to ${this.maxSubscriptions} items`);
2213
+ }
2214
+ }
1737
2215
  }
1738
2216
  // Add method to remove specific subscriptions
1739
2217
  removeTransferSubscription(account, callback) {