Skip to content

Commit

Permalink
Account:
Browse files Browse the repository at this point in the history
* docu improved
* get_feed, get_blog, get_blog_entries added
* get_account_votes added
* fix timezone
Amount
* export to json and str fixed
Block
* change_block_number added
Blockchain
* get_estimated_block_num added
Comment
* dates and Amounts are now converted
* json_export adapted
* get_reblogged_by added
* delete_comment added
Storage
* 2 nodes removed from default
Utils
* timezone information added to formatTimeString
Unit tests
* more tests added for account, amount, comment, price and transaction
  • Loading branch information
holgern committed Feb 27, 2018
1 parent ab3a817 commit 7356a51
Show file tree
Hide file tree
Showing 17 changed files with 406 additions and 59 deletions.
148 changes: 122 additions & 26 deletions beem/account.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from .blockchainobject import BlockchainObject
from .utils import formatTimeString
from beem.amount import Amount
from datetime import datetime, timedelta
from datetime import datetime, timedelta, timezone
from beembase import operations
from beembase.account import PrivateKey, PublicKey
import json
Expand Down Expand Up @@ -47,7 +47,6 @@ class Account(BlockchainObject):
def __init__(
self,
account,
id_item="name",
full=True,
lazy=False,
steem_instance=None
Expand Down Expand Up @@ -77,6 +76,7 @@ def refresh(self):
if not account:
raise AccountDoesNotExistsException(self.identifier)
self.identifier = account["name"]
self.steem.refresh_data()

super(Account, self).__init__(account, id_item="name")

Expand All @@ -87,6 +87,8 @@ def getSimilarAccountNames(self, limit=5):

@property
def name(self):
""" Returns the account name
"""
return self["name"]

@property
Expand All @@ -97,6 +99,8 @@ def profile(self):

@property
def rep(self):
""" Returns the account reputation
"""
return self.reputation()

def print_info(self, force_refresh=False, return_str=False):
Expand All @@ -111,28 +115,34 @@ def print_info(self, force_refresh=False, return_str=False):
ret += str(round(self.steem_power(), 2)) + " SP, "
ret += str(self.balances["available"][0]) + ", " + str(self.balances["available"][1])
bandwidth = self.get_bandwidth()
ret += "\n"
ret += "Remaining Bandwidth: " + str(round(100 - bandwidth["used"] / bandwidth["allocated"] * 100, 2)) + " %"
ret += " (" + str(round(bandwidth["used"] / 1024)) + " kb of " + str(round(bandwidth["allocated"] / 1024 / 1024)) + " mb)"
if bandwidth["allocated"] > 0:
ret += "\n"
ret += "Remaining Bandwidth: " + str(round(100 - bandwidth["used"] / bandwidth["allocated"] * 100, 2)) + " %"
ret += " (" + str(round(bandwidth["used"] / 1024)) + " kb of " + str(round(bandwidth["allocated"] / 1024 / 1024)) + " mb)"
if return_str:
return ret
print(ret)

def reputation(self, precision=2):
""" Returns the account reputation
"""
rep = int(self['reputation'])
if rep == 0:
return 25
score = max([math.log10(abs(rep)) - 9, 0]) * 9 + 25
return 25.
score = max([math.log10(abs(rep)) - 9, 0])
if rep < 0:
score = 50 - score
score *= -1
score = (score * 9.) + 25.
if precision is not None:
return round(score, precision)
else:
return score

def voting_power(self, precision=2, with_regeneration=True):
""" Returns the account voting power
"""
if with_regeneration:
diff_in_seconds = (datetime.utcnow() - formatTimeString(self["last_vote_time"])).total_seconds()
diff_in_seconds = (datetime.utcnow().replace(tzinfo=timezone.utc) - formatTimeString(self["last_vote_time"])).total_seconds()
regenerated_vp = diff_in_seconds * 10000 / 86400 / 5 / 100
else:
regenerated_vp = 0
Expand All @@ -147,14 +157,17 @@ def voting_power(self, precision=2, with_regeneration=True):
return total_vp

def steem_power(self, onlyOwnSP=False):
""" Returns the account steem power
"""
if onlyOwnSP:
vests = Amount(self["vesting_shares"])
else:
vests = Amount(self["vesting_shares"]) - Amount(self["delegated_vesting_shares"]) + Amount(self["received_vesting_shares"])
return self.steem.vests_to_sp(vests)

def get_voting_value_SBD(self, voting_weight=100, voting_power=None, steem_power=None, precision=2):

""" Returns the account voting value in SBD
"""
if voting_power is None:
voting_power = self.voting_power()
if steem_power is None:
Expand All @@ -166,33 +179,111 @@ def get_voting_value_SBD(self, voting_weight=100, voting_power=None, steem_power
return round(VoteValue, precision)

def get_recharge_time_str(self, voting_power_goal=100):
""" Returns the account recharge time
"""
hours = math.floor(self.get_recharge_hours(voting_power_goal=voting_power_goal, precision=3))
minutes = math.floor(self.get_recharge_reminder_minutes(voting_power_goal=voting_power_goal, precision=0))
return str(hours) + ":" + str(minutes).zfill(2)

def get_recharge_hours(self, voting_power_goal=100, precision=2):
""" Returns the account voting power recharge time in hours
"""
missing_vp = voting_power_goal - self.voting_power(precision=10)
if missing_vp < 0:
return 0
recharge_seconds = missing_vp * 100 * 5 * 86400 / 10000
return round(recharge_seconds / 60 / 60, precision)

def get_recharge_reminder_minutes(self, voting_power_goal=100, precision=0):
""" Returns the account voting power recharge time in minutes
"""
hours = self.get_recharge_hours(voting_power_goal=voting_power_goal, precision=5)
reminder_in_minuts = (hours - math.floor(hours)) * 60
return round(reminder_in_minuts, precision)

def get_followers(self):
return [
x['follower'] for x in self._get_followers(direction="follower")
]
def get_feed(self, entryId=0, limit=100, raw_data=True, account=None):
if account is None:
account = self["name"]
self.steem.register_apis(["follow"])
if raw_data:
return [
c for c in self.steem.rpc.get_feed(account, entryId, limit, api='follow')
]
else:
from .comment import Comment
return [
Comment(c['comment'], steem_instance=self.steem) for c in self.steem.rpc.get_feed(account, entryId, limit, api='follow')
]

def get_following(self):
return [
x['following'] for x in self._get_followers(direction="following")
]
def get_blog_entries(self, entryId=0, limit=100, raw_data=True, account=None):
if account is None:
account = self["name"]
self.steem.register_apis(["follow"])
if raw_data:
return [
c for c in self.steem.rpc.get_blog_entries(account, entryId, limit, api='follow')
]
else:
from .comment import Comment
return [
Comment(c, steem_instance=self.steem) for c in self.steem.rpc.get_blog_entries(account, entryId, limit, api='follow')
]

def get_blog(self, entryId=0, limit=100, raw_data=True, account=None):
if account is None:
account = self["name"]
self.steem.register_apis(["follow"])
if raw_data:
return [
c for c in self.steem.rpc.get_blog(account, entryId, limit, api='follow')
]
else:
from .comment import Comment
return [
Comment(c["comment"], steem_instance=self.steem) for c in self.steem.rpc.get_blog(account, entryId, limit, api='follow')
]

def get_blog_account(self, account=None):
if account is None:
account = self["name"]
self.steem.register_apis(["follow"])
return self.steem.rpc.get_blog_authors(account, api='follow')

def get_follow_count(self, account=None):
""" get_follow_count """
if account is None:
account = self["name"]
self.steem.register_apis(["follow"])
return self.steem.rpc.get_follow_count(account, api='follow')

def get_followers(self, raw_data=True):
""" Returns the account followers as list
"""
if raw_data:
return [
x['follower'] for x in self._get_followers(direction="follower")
]
else:
return [
Account(x['follower'], steem_instance=self.steem) for x in self._get_followers(direction="follower")
]

def get_following(self, raw_data=True):
""" Returns who the account is following as list
"""
if raw_data:
return [
x['following'] for x in self._get_followers(direction="following")
]
else:
return [
Account(x['following'], steem_instance=self.steem) for x in self._get_followers(direction="following")
]

def _get_followers(self, direction="follower", last_user=""):
""" Help function, used in get_followers and get_following
"""
self.steem.register_apis(["follow"])
if direction == "follower":
followers = self.steem.rpc.get_followers(self.name, last_user, "blog", 100, api='follow')
elif direction == "following":
Expand Down Expand Up @@ -291,7 +382,7 @@ def interest(self):
"interest": interest_amount,
"last_payment": last_payment,
"next_payment": next_payment,
"next_payment_duration": next_payment - datetime.now(),
"next_payment_duration": next_payment - datetime.now(timezone.utc),
"interest_rate": interest_rate,
}

Expand Down Expand Up @@ -323,7 +414,7 @@ def get_bandwidth(self, bandwidth_type=1, account=None, raw_data=False):

total_seconds = 604800
date_bandwidth = formatTimeString(self["last_bandwidth_update"])
seconds_since_last_update = datetime.utcnow() - date_bandwidth
seconds_since_last_update = datetime.utcnow().replace(tzinfo=timezone.utc) - date_bandwidth
seconds_since_last_update = seconds_since_last_update.total_seconds()
average_bandwidth = float(self["average_bandwidth"])
used_bandwidth = 0
Expand All @@ -342,24 +433,29 @@ def get_owner_history(self, account=None):
account = self["name"]
return self.steem.rpc.get_owner_history(account)

def get_recovery_request(self, account=None):
""" get_recovery_request """
def get_conversion_requests(self, account=None):
""" get_owner_history """
if account is None:
account = self["name"]
return self.steem.rpc.get_recovery_request(account)
return self.steem.rpc.get_conversion_requests(account)

def get_follow_count(self, account=None):
""" get_follow_count """
def get_recovery_request(self, account=None):
""" get_recovery_request """
if account is None:
account = self["name"]
return self.steem.rpc.get_follow_count(account, api="follow")
return self.steem.rpc.get_recovery_request(account)

def verify_account_authority(self, keys, account=None):
""" verify_account_authority """
if account is None:
account = self["name"]
return self.steem.rpc.verify_account_authority(account, keys)

def get_account_votes(self, account=None):
if account is None:
account = self["name"]
return self.steem.rpc.get_account_votes(account)

def history(
self, limit=100,
only_ops=[], exclude_ops=[]
Expand Down
4 changes: 2 additions & 2 deletions beem/amount.py
Original file line number Diff line number Diff line change
Expand Up @@ -142,11 +142,11 @@ def asset(self):
def json(self):
return {
"amount": int(self),
"asset_id": self["asset"]["id"]
"symbol": self["asset"]["symbol"]
}

def __str__(self):
return "{:,.{prec}f} {}".format(
return "{:.{prec}f} {}".format(
self["amount"],
self["symbol"],
prec=self["asset"]["precision"]
Expand Down
4 changes: 4 additions & 0 deletions beem/block.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,10 @@ def time(self):
"""
return parse_time(self['timestamp'])

def change_block_number(self, number):
self.identifier = number
self.refresh()

def ops(self):
ops = []
for tx in self["transactions"]:
Expand Down
28 changes: 26 additions & 2 deletions beem/blockchain.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from beembase.operationids import getOperationNameForId
from .amount import Amount
from datetime import datetime
import math


class Blockchain(object):
Expand Down Expand Up @@ -54,7 +55,7 @@ def __init__(
raise ValueError("invalid value for 'mode'!")

def get_current_block_num(self):
""" This call returns the current block
""" This call returns the current block number
.. note:: The block number returned depends on the ``mode`` used
when instanciating from this class.
Expand All @@ -72,6 +73,29 @@ def get_current_block(self):
steem_instance=self.steem
)

def get_estimated_block_num(self, date, estimateForwards=False):
""" This call estimates the block number based on a given date
:param datetime date: block time for which a block number is estimated
.. note:: The block number returned depends on the ``mode`` used
when instanciating from this class.
"""
block_time_seconds = 3
if estimateForwards:
block_offset = 10
first_block = Block(block_offset, steem_instance=self.steem)
time_diff = date - first_block.time()
return math.floor(time_diff.total_seconds() / block_time_seconds + block_offset.identifier)
else:
last_block = self.get_current_block()
time_diff = last_block.time() - date
block_number = math.floor(last_block.identifier - time_diff.total_seconds() / block_time_seconds)
if block_number > last_block.identifier:
return last_block.identifier
else:
block_number

def block_time(self, block_num):
""" Returns a datetime of the block with the given block
number.
Expand Down Expand Up @@ -220,7 +244,7 @@ def awaitTxConfirmation(self, transaction, limit=10):
included into a block
.. note:: If you want instant confirmation, you need to instantiate
class:`steem.blockchain.Blockchain` with
class:`beem.blockchain.Blockchain` with
``mode="head"``, otherwise, the call will wait until
confirmed in an irreversible block.
Expand Down
Loading

0 comments on commit 7356a51

Please sign in to comment.