morphit/node_modules/@beblurt/dblurt/lib/helpers/tools.js
Morphit Team 24240cef4c
Some checks failed
morphit-release / Build + publish release tarball (push) Has been cancelled
Reputation flags clearable across all four signals; names and avatars stop vanishing
2026-07-23 14:28:04 -07:00

190 lines
8.6 KiB
JavaScript

"use strict";
/**
* @file Account helpers.
* @author BeBlurt <https://beblurt.com/@beblurt>
* @description Special account functions
* @license
* Copyright (c) 2022 BeBlurt. All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistribution of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* 2. Redistribution in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors
* may be used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*
* You acknowledge that this software is not designed, licensed or intended for use
* in the design, construction, operation or maintenance of any military facility.
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.Tools = void 0;
const asset_1 = require("../chain/asset");
const serializer_1 = require("../chain/serializer");
const ByteBuffer = require('bytebuffer/dist/bytebuffer');
const BLURT_VOTING_MANA_REGENERATION_SECONDS = (5 * 60 * 60 * 24); // 5 day (432000 seconds)
const BLURT_100_PERCENT = 10000;
const BLURT_UPVOTE_LOCKOUT_SECONDS = (60 * 60 * 12); // 12 hours (43200 seconds)
class Tools {
constructor(client) {
this.client = client;
}
/** Convenience for calling `condenser_api`. */
call(method, params) {
return this.client.call('condenser_api', method, params);
}
/**
* Get voting mana for an account.
*
* @param name Account name.
* @returns Current and maximum voting mana calculated from account vesting state.
*/
async getAccountMana(name) {
try {
/** get Account */
const accounts = await this.call('get_accounts', [[name]]);
if (accounts.length > 0) {
const account = accounts[0];
/** Vesting */
let net_vesting_shares = asset_1.Asset.from(account.vesting_shares);
net_vesting_shares = net_vesting_shares.subtract(account.delegated_vesting_shares);
net_vesting_shares = net_vesting_shares.add(account.received_vesting_shares);
/** Vesting withdraw rate */
const vesting_withdraw_rate = asset_1.Asset.from(account.vesting_withdraw_rate);
/** Mana Calculation */
let current_mana = parseInt(account.voting_manabar.current_mana, 10);
const now = Math.round(Date.now() / 1000);
const elapsed = now - account.voting_manabar.last_update_time;
const max_mana = (net_vesting_shares.amount - vesting_withdraw_rate.amount) * 1000000;
const regenerated_mana = (elapsed * max_mana) / BLURT_VOTING_MANA_REGENERATION_SECONDS;
current_mana += regenerated_mana;
if (current_mana >= max_mana) {
current_mana = max_mana;
}
return { current_mana, max_mana };
}
else {
throw new Error('invalid account name');
}
}
catch (e) {
throw e;
}
}
/**
* Estimate the vote value for a post from mana, reward fund and chain properties.
*
* @param voteWeight Vote weight percentage.
* @param mana Current and maximum voting mana for the account.
* @param net_rshares Net rshares of the post.
* @param cashout_time Cashout time of the post in milliseconds.
* @param DGP Dynamic global properties.
* @param REWARD_FUND Reward fund data.
* @returns Estimated vote value rounded to three decimals.
*/
getAccountVoteValue(voteWeight, mana, net_rshares, cashout_time, DGP, REWARD_FUND) {
try {
const postRshares = typeof net_rshares === 'string' ? parseInt(net_rshares, 10) : net_rshares;
const cashoutDelta = (cashout_time - Date.now()) / 1000;
if (cashoutDelta <= 0) {
return 0;
}
/** Dynamic Global Properties */
const vote_power_reserve_rate = DGP.vote_power_reserve_rate;
const vestedBlurt = asset_1.Asset.from(DGP.total_vesting_fund_blurt);
const currentSupply = asset_1.Asset.from(DGP.current_supply);
const ratio = vestedBlurt.amount / currentSupply.amount;
let usedMana = (mana.current_mana * (voteWeight * 100) * 60 * 60 * 24) / BLURT_100_PERCENT;
const maxVoteDenom = vote_power_reserve_rate * BLURT_VOTING_MANA_REGENERATION_SECONDS;
usedMana = (usedMana + maxVoteDenom - 1) / maxVoteDenom;
let rshares = usedMana;
if (cashoutDelta < BLURT_UPVOTE_LOCKOUT_SECONDS) {
rshares = (rshares * cashoutDelta) / BLURT_UPVOTE_LOCKOUT_SECONDS;
}
const totalRshares = rshares + postRshares;
const S = parseInt(REWARD_FUND.content_constant, 10);
const claims = (totalRshares * (totalRshares + 2 * S)) / (totalRshares + 4 * S);
const rewardBalance = asset_1.Asset.from(REWARD_FUND.reward_balance).amount;
const recentClaims = parseInt(REWARD_FUND.recent_claims, 10);
const rewards = rewardBalance / recentClaims;
const postValue = claims * rewards * ratio;
const totPost = postValue * (rshares / totalRshares);
return parseFloat(totPost.toFixed(3));
}
catch (e) {
throw e;
}
}
/**
* Get the conversion of VESTS to BLURT.
* @param VESTS VESTS value.
* @param DGP Dynamic global properties from `condenser_api.get_dynamic_global_properties`.
*/
convertVESTS(VESTS, DGP) {
try {
const total_vesting_fund_blurt = asset_1.Asset.from(DGP.total_vesting_fund_blurt).amount;
const total_vesting_shares = asset_1.Asset.from(DGP.total_vesting_shares).amount;
return Math.round(((total_vesting_fund_blurt * VESTS) / total_vesting_shares) * 1000) / 1000;
}
catch (e) {
throw e;
}
}
serialize(serializer, data) {
const buffer = new ByteBuffer(ByteBuffer.DEFAULT_CAPACITY, ByteBuffer.LITTLE_ENDIAN);
serializer(buffer, data);
buffer.flip();
return Buffer.from(buffer.toBuffer());
}
buildWitnessSetPropertiesOp(owner, props) {
const data = {
extensions: [], owner, props: []
};
for (const key of Object.keys(props)) {
let type;
switch (key) {
case 'key':
case 'new_signing_key':
type = serializer_1.Types.PublicKey;
break;
case 'account_subsidy_budget':
case 'account_subsidy_decay':
case 'maximum_block_size':
type = serializer_1.Types.UInt32;
break;
case 'url':
type = serializer_1.Types.String;
break;
case 'account_creation_fee':
case 'operation_flat_fee':
case 'bandwidth_kbytes_fee':
case 'proposal_fee':
type = serializer_1.Types.Asset;
break;
default:
throw new Error(`Unknown witness prop: ${key}`);
}
data.props.push([key, this.serialize(type, props[key])]);
}
data.props.sort((a, b) => a[0].localeCompare(b[0]));
return ['witness_set_properties', data];
}
}
exports.Tools = Tools;