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/DOCUMENTATION.md +693 -1
- package/README.md +13 -0
- package/dist/adapters/mongodb.adapter.js +21 -30
- package/dist/adapters/mongodb.adapter.js.map +1 -1
- package/dist/adapters/postgresql.adapter.js +16 -16
- package/dist/adapters/postgresql.adapter.js.map +1 -1
- package/dist/adapters/sqlite.adapter.js +17 -17
- package/dist/adapters/sqlite.adapter.js.map +1 -1
- package/dist/api.js +2 -0
- package/dist/api.js.map +1 -1
- package/dist/builders.d.ts +269 -1
- package/dist/builders.js +883 -1
- package/dist/builders.js.map +1 -1
- package/dist/config.js +2 -2
- package/dist/config.js.map +1 -1
- package/dist/streamer.d.ts +105 -10
- package/dist/streamer.js +539 -61
- package/dist/streamer.js.map +1 -1
- package/dist/types/hive-stream.d.ts +306 -0
- package/dist/utils.d.ts +442 -0
- package/dist/utils.js +1423 -0
- package/dist/utils.js.map +1 -1
- package/package.json +4 -5
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
|
|
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
|
-
|
|
91
|
+
lastCacheCleanup = Date.now();
|
|
92
|
+
utils = utils_1.Utils;
|
|
78
93
|
money = {
|
|
79
|
-
parseAssetAmount: (rawAmount) =>
|
|
80
|
-
formatAmount: (amount, precision) =>
|
|
81
|
-
formatAssetAmount: (amount, symbol, precision) =>
|
|
82
|
-
calculatePercentageAmount: (amount, percentage, precision) =>
|
|
83
|
-
calculateBasisPointsAmount: (amount, basisPoints, precision) =>
|
|
84
|
-
splitAmountByBasisPoints: (amount, basisPoints, precision) =>
|
|
85
|
-
splitAmountByPercentage: (amount, percentages, precision) =>
|
|
86
|
-
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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:
|
|
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 =
|
|
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 :
|
|
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
|
|
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 =
|
|
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
|
|
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[
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 ?
|
|
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 =
|
|
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 =
|
|
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
|
|
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
|
|
1606
|
+
return utils_1.Utils.getAccountTransfers(this.client, account, from, limit);
|
|
1365
1607
|
}
|
|
1366
1608
|
transferHiveTokens(from, to, amount, symbol, memo = '') {
|
|
1367
|
-
return
|
|
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
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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
|
|
1835
|
+
return utils_1.Utils.transferHiveTokensMultiple(this.client, this.config, from, accounts, amount, symbol, memo);
|
|
1594
1836
|
}
|
|
1595
1837
|
broadcastOperations(operations, signingKeys) {
|
|
1596
|
-
|
|
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
|
|
1859
|
+
return utils_1.Utils.broadcastMultiSigOperations(this.client, operations, signingKeys);
|
|
1600
1860
|
}
|
|
1601
1861
|
createAuthority(keyAuths = [], accountAuths = [], weightThreshold = 1) {
|
|
1602
|
-
return
|
|
1862
|
+
return utils_1.Utils.createAuthority(keyAuths, accountAuths, weightThreshold);
|
|
1603
1863
|
}
|
|
1604
1864
|
updateAccountAuthorities(account, authorityUpdate, signingKeys) {
|
|
1605
|
-
return
|
|
1865
|
+
return utils_1.Utils.updateAccountAuthorities(this.client, this.config, account, authorityUpdate, signingKeys);
|
|
1606
1866
|
}
|
|
1607
1867
|
escrowTransfer(options, signingKeys) {
|
|
1608
|
-
return
|
|
1868
|
+
return utils_1.Utils.escrowTransfer(this.client, this.config, options, signingKeys);
|
|
1609
1869
|
}
|
|
1610
1870
|
escrowApprove(options, signingKeys) {
|
|
1611
|
-
return
|
|
1871
|
+
return utils_1.Utils.escrowApprove(this.client, this.config, options, signingKeys);
|
|
1612
1872
|
}
|
|
1613
1873
|
escrowDispute(options, signingKeys) {
|
|
1614
|
-
return
|
|
1874
|
+
return utils_1.Utils.escrowDispute(this.client, this.config, options, signingKeys);
|
|
1615
1875
|
}
|
|
1616
1876
|
escrowRelease(options, signingKeys) {
|
|
1617
|
-
return
|
|
1877
|
+
return utils_1.Utils.escrowRelease(this.client, this.config, options, signingKeys);
|
|
1618
1878
|
}
|
|
1619
1879
|
recurrentTransfer(options, signingKeys) {
|
|
1620
|
-
return
|
|
1880
|
+
return utils_1.Utils.recurrentTransfer(this.client, this.config, options, signingKeys);
|
|
1621
1881
|
}
|
|
1622
1882
|
createProposal(options, signingKeys) {
|
|
1623
|
-
return
|
|
1883
|
+
return utils_1.Utils.createProposal(this.client, this.config, options, signingKeys);
|
|
1624
1884
|
}
|
|
1625
1885
|
updateProposalVotes(options, signingKeys) {
|
|
1626
|
-
return
|
|
1886
|
+
return utils_1.Utils.updateProposalVotes(this.client, this.config, options, signingKeys);
|
|
1627
1887
|
}
|
|
1628
1888
|
removeProposals(options, signingKeys) {
|
|
1629
|
-
return
|
|
1889
|
+
return utils_1.Utils.removeProposals(this.client, this.config, options, signingKeys);
|
|
1630
1890
|
}
|
|
1631
1891
|
transferHiveEngineTokens(from, to, symbol, quantity, memo = '') {
|
|
1632
|
-
return
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
1910
|
+
return utils_1.Utils.downvote(this.client, this.config, this.username, votePercentage, username, permlink);
|
|
1651
1911
|
}
|
|
1652
1912
|
getTransaction(blockNumber, transactionId) {
|
|
1653
|
-
return
|
|
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
|
|
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(
|
|
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) {
|