Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: holgern/beem
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 0.20.23
Choose a base ref
...
head repository: holgern/beem
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 0.21.0
Choose a head ref
  • 11 commits
  • 23 files changed
  • 4 contributors

Commits on Jul 31, 2019

  1. Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    fb38d09 View commit details

Commits on Aug 12, 2019

  1. Copy the full SHA
    7027556 View commit details

Commits on Aug 26, 2019

  1. Copy the full SHA
    170485f View commit details

Commits on Aug 27, 2019

  1. Prepare changes for HF21

    * operations for account_update2, create_proposal, update_proposal_votes and remove_proposal were added
    * update_proposal_votes was added to steem
    * update_account_jsonmetadata was added to account
    * new beempy delete were added
    holgern committed Aug 27, 2019
    Copy the full SHA
    bd2de72 View commit details

Commits on Aug 28, 2019

  1. More improvements for HF21

    * add options use_tags_api to use database api to get comments
    * fix get_similar_account_names
    * add more try expect to fail back to condenser api
    holgern committed Aug 28, 2019
    Copy the full SHA
    343f480 View commit details
  2. Merge pull request #197 from pablomat/master

    Add support for Pulsar to be used in future EFTG iterations
    holgern authored Aug 28, 2019
    Copy the full SHA
    c1b4c86 View commit details
  3. Merge pull request #200 from holgern/pyup-scheduled-update-2019-08-26

    Scheduled weekly dependency update for week 34
    holgern authored Aug 28, 2019
    Copy the full SHA
    5a5c16e View commit details
  4. Add downvoting power

    holgern committed Aug 28, 2019
    Copy the full SHA
    e205a7f View commit details
  5. Update changelog

    holgern committed Aug 28, 2019
    Copy the full SHA
    713a2ad View commit details
  6. add tox

    holgern committed Aug 28, 2019
    Copy the full SHA
    ef0a0d5 View commit details
  7. Copy the full SHA
    635bcd7 View commit details
Showing with 453 additions and 110 deletions.
  1. +2 −2 .travis.yml
  2. +21 −0 CHANGELOG.rst
  3. +168 −73 beem/account.py
  4. +1 −2 beem/amount.py
  5. +1 −1 beem/blockchain.py
  6. +28 −2 beem/cli.py
  7. +26 −6 beem/comment.py
  8. +1 −1 beem/price.py
  9. +36 −6 beem/steem.py
  10. +9 −0 beem/utils.py
  11. +1 −1 beem/version.py
  12. +11 −4 beem/vote.py
  13. +1 −1 beem/wallet.py
  14. +1 −1 beemapi/graphenerpc.py
  15. +2 −2 beemapi/steemnoderpc.py
  16. +1 −1 beemapi/version.py
  17. +10 −0 beembase/operationids.py
  18. +119 −3 beembase/operations.py
  19. +1 −1 beembase/version.py
  20. +10 −0 beemgraphenebase/chains.py
  21. +1 −1 beemgraphenebase/version.py
  22. +1 −1 requirements-test.txt
  23. +1 −1 setup.py
4 changes: 2 additions & 2 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -57,8 +57,8 @@ before_install:
- pip install --upgrade pip
- pip install --upgrade wheel
# Set numpy version first, other packages link against it
- pip install six nose coverage codecov tox-travis pytest pytest-cov coveralls codacy-coverage parameterized secp256k1prp cryptography scrypt
- pip install pycryptodomex pyyaml appdirs pylibscrypt
- pip install six nose coverage codecov pytest pytest-cov coveralls codacy-coverage parameterized secp256k1prp cryptography scrypt
- pip install pycryptodomex pyyaml appdirs pylibscrypt tox
- pip install ecdsa requests future websocket-client pytz six Click events prettytable

script:
21 changes: 21 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
@@ -1,5 +1,26 @@
Changelog
=========
0.21.0
------
* First release for HF21
* get_downvoting_power added to account
* get_downvote_manabar added to account
* add options use_tags_api to use database api to get comments
* fix get_similar_account_names
* add more try expect to fail back to condenser api
* operations for account_update2, create_proposal, update_proposal_votes and remove_proposal were added
* update_proposal_votes was added to steem
* update_account_jsonmetadata was added to account
* new beempy delete were added

0.20.23
-------
* Switch to next node, when current node has the necesary api not enabled
* handle Client returned invalid format. Expected JSON! and switch to next node
* More checks added
* get_estimated_block_num is faster and uses BlockHeader
* exclude_limited=False is default now for get_nodes

0.20.22
-------
* Fix #195 - comment.downvote(100) will now downvote with 100%, negative numbers are not allowed anymore
241 changes: 168 additions & 73 deletions beem/account.py
Original file line number Diff line number Diff line change
@@ -99,7 +99,7 @@ def refresh(self):
return
self.steem.rpc.set_next_node_on_empty_reply(self.steem.rpc.get_use_appbase())
if self.steem.rpc.get_use_appbase():
account = self.steem.rpc.find_accounts({'accounts': [self.identifier]}, api="database")
account = self.steem.rpc.find_accounts({'accounts': [self.identifier]}, api="database")
else:
if self.full:
account = self.steem.rpc.get_accounts(
@@ -329,6 +329,7 @@ def print_info(self, force_refresh=False, return_str=False, use_table=False, **k
t.align = "l"
t.add_row(["Name (rep)", self.name + " (%.2f)" % (self.rep)])
t.add_row(["Voting Power", "%.2f %%, " % (self.get_voting_power())])
t.add_row(["Downvoting Power", "%.2f %%, " % (self.get_downvoting_power())])
t.add_row(["Vote Value", "%.2f $" % (self.get_voting_value_SBD())])
t.add_row(["Last vote", "%s ago" % last_vote_time_str])
t.add_row(["Full in ", "%s" % (self.get_recharge_time_str())])
@@ -360,8 +361,10 @@ def print_info(self, force_refresh=False, return_str=False, use_table=False, **k
ret = self.name + " (%.2f) \n" % (self.rep)
ret += "--- Voting Power ---\n"
ret += "%.2f %%, " % (self.get_voting_power())
ret += " VP = %.2f $\n" % (self.get_voting_value_SBD())
ret += " %.2f $\n" % (self.get_voting_value_SBD())
ret += "full in %s \n" % (self.get_recharge_time_str())
ret += "--- Downvoting Power ---\n"
ret += "%.2f %% \n" % (self.get_downvoting_power())
ret += "--- Balance ---\n"
ret += "%.2f SP, " % (self.get_steem_power())
ret += "%s, %s\n" % (str(self.balances["available"][0]), str(self.balances["available"][1]))
@@ -391,9 +394,12 @@ def get_reputation(self):
return None
self.steem.rpc.set_next_node_on_empty_reply(False)
if self.steem.rpc.get_use_appbase():
rep = self.steem.rpc.get_account_reputations({'account_lower_bound': self["name"], 'limit': 1}, api="follow")['reputations']
if len(rep) > 0:
rep = int(rep[0]['reputation'])
try:
rep = self.steem.rpc.get_account_reputations({'account_lower_bound': self["name"], 'limit': 1}, api="follow")['reputations']
if len(rep) > 0:
rep = int(rep[0]['reputation'])
except:
rep = int(self['reputation'])
else:
rep = int(self['reputation'])
return reputation_to_score(rep)
@@ -420,6 +426,30 @@ def get_manabar(self):
return {"last_mana": last_mana, "last_update_time": last_update_time,
"current_mana": current_mana, "max_mana": max_mana, "current_mana_pct": current_mana_pct}

def get_downvote_manabar(self):
""" Return downvote manabar
"""
if "downvote_manabar" not in self:
return None
max_mana = self.get_effective_vesting_shares() / 4
if max_mana == 0:
props = self.steem.get_chain_properties()
required_fee_steem = Amount(props["account_creation_fee"], steem_instance=self.steem)
max_mana = int(self.steem.sp_to_vests(required_fee_steem) / 4)
last_mana = int(self["downvote_manabar"]["current_mana"])
last_update_time = self["downvote_manabar"]["last_update_time"]
last_update = datetime.utcfromtimestamp(last_update_time)
diff_in_seconds = (addTzInfo(datetime.utcnow()) - addTzInfo(last_update)).total_seconds()
current_mana = int(last_mana + diff_in_seconds * max_mana / STEEM_VOTING_MANA_REGENERATION_SECONDS)
if current_mana > max_mana:
current_mana = max_mana
if max_mana > 0:
current_mana_pct = current_mana / max_mana * 100
else:
current_mana_pct = 0
return {"last_mana": last_mana, "last_update_time": last_update_time,
"current_mana": current_mana, "max_mana": max_mana, "current_mana_pct": current_mana_pct}

def get_voting_power(self, with_regeneration=True):
""" Returns the account voting power in the range of 0-100%
"""
@@ -446,6 +476,26 @@ def get_voting_power(self, with_regeneration=True):
return 0
return total_vp

def get_downvoting_power(self, with_regeneration=True):
""" Returns the account downvoting power in the range of 0-100%
"""
if "downvote_manabar" not in self:
return 0

manabar = self.get_downvote_manabar()
if with_regeneration:
total_down_vp = manabar["current_mana_pct"]
else:
if manabar["max_mana"] > 0:
total_down_vp = manabar["last_mana"] / manabar["max_mana"] * 100
else:
total_down_vp = 0
if total_down_vp > 100:
return 100
if total_down_vp < 0:
return 0
return total_down_vp

def get_vests(self, only_own_vests=False):
""" Returns the account vests
"""
@@ -623,32 +673,38 @@ def get_feed(self, start_entry_id=0, limit=100, raw_data=False, short_entries=Fa
if not self.steem.is_connected():
return None
self.steem.rpc.set_next_node_on_empty_reply(False)
if raw_data and short_entries and self.steem.rpc.get_use_appbase():
return [
c for c in self.steem.rpc.get_feed_entries({'account': account, 'start_entry_id': start_entry_id, 'limit': limit}, api='follow')["feed"]
]
elif raw_data and short_entries and not self.steem.rpc.get_use_appbase():
return [
c for c in self.steem.rpc.get_feed_entries(account, start_entry_id, limit, api='follow')
]
elif raw_data and self.steem.rpc.get_use_appbase():
return [
c for c in self.steem.rpc.get_feed({'account': account, 'start_entry_id': start_entry_id, 'limit': limit}, api='follow')["feed"]
]
elif raw_data and not self.steem.rpc.get_use_appbase():
return [
c for c in self.steem.rpc.get_feed(account, start_entry_id, limit, api='follow')
]
elif not raw_data and self.steem.rpc.get_use_appbase():
from .comment import Comment
return [
Comment(c['comment'], steem_instance=self.steem) for c in self.steem.rpc.get_feed({'account': account, 'start_entry_id': start_entry_id, 'limit': limit}, api='follow')["feed"]
]
else:
from .comment import Comment
return [
Comment(c['comment'], steem_instance=self.steem) for c in self.steem.rpc.get_feed(account, start_entry_id, limit, api='follow')
]
success = True
if self.steem.rpc.get_use_appbase():
try:
if raw_data and short_entries:
return [
c for c in self.steem.rpc.get_feed_entries({'account': account, 'start_entry_id': start_entry_id, 'limit': limit}, api='follow')["feed"]
]
elif raw_data:
return [
c for c in self.steem.rpc.get_feed({'account': account, 'start_entry_id': start_entry_id, 'limit': limit}, api='follow')["feed"]
]
elif not raw_data:
from .comment import Comment
return [
Comment(c['comment'], steem_instance=self.steem) for c in self.steem.rpc.get_feed({'account': account, 'start_entry_id': start_entry_id, 'limit': limit}, api='follow')["feed"]
]
except:
success = False
if not self.steem.rpc.get_use_appbase() or not success:
if raw_data and short_entries:
return [
c for c in self.steem.rpc.get_feed_entries(account, start_entry_id, limit, api='follow')
]
elif raw_data:
return [
c for c in self.steem.rpc.get_feed(account, start_entry_id, 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, start_entry_id, limit, api='follow')
]

def get_feed_entries(self, start_entry_id=0, limit=100, raw_data=True,
account=None):
@@ -726,41 +782,50 @@ def get_blog(self, start_entry_id=0, limit=100, raw_data=False, short_entries=Fa
if not self.steem.is_connected():
raise OfflineHasNoRPCException("No RPC available in offline mode!")
self.steem.rpc.set_next_node_on_empty_reply(False)
if raw_data and short_entries and self.steem.rpc.get_use_appbase():
ret = self.steem.rpc.get_blog_entries({'account': account, 'start_entry_id': start_entry_id, 'limit': limit}, api='follow')
if isinstance(ret, dict) and "blog" in ret:
ret = ret["blog"]
return [
c for c in ret
]
elif raw_data and short_entries and not self.steem.rpc.get_use_appbase():
return [
c for c in self.steem.rpc.get_blog_entries(account, start_entry_id, limit, api='follow')
]
elif raw_data and self.steem.rpc.get_use_appbase():
ret = self.steem.rpc.get_blog({'account': account, 'start_entry_id': start_entry_id, 'limit': limit}, api='follow')
if isinstance(ret, dict) and "blog" in ret:
ret = ret["blog"]
return [
c for c in ret
]
elif raw_data and not self.steem.rpc.get_use_appbase():
return [
c for c in self.steem.rpc.get_blog(account, start_entry_id, limit, api='follow')
]
elif not raw_data and self.steem.rpc.get_use_appbase():
from .comment import Comment
ret = self.steem.rpc.get_blog({'account': account, 'start_entry_id': start_entry_id, 'limit': limit}, api='follow')
if isinstance(ret, dict) and "blog" in ret:
ret = ret["blog"]
return [
Comment(c["comment"], steem_instance=self.steem) for c in ret
]
else:
from .comment import Comment
return [
Comment(c["comment"], steem_instance=self.steem) for c in self.steem.rpc.get_blog(account, start_entry_id, limit, api='follow')
]
success = True
if self.steem.rpc.get_use_appbase():
try:
if raw_data and short_entries:
ret = self.steem.rpc.get_blog_entries({'account': account, 'start_entry_id': start_entry_id, 'limit': limit}, api='follow')
if isinstance(ret, dict) and "blog" in ret:
ret = ret["blog"]
return [
c for c in ret
]
elif raw_data:
ret = self.steem.rpc.get_blog({'account': account, 'start_entry_id': start_entry_id, 'limit': limit}, api='follow')
if isinstance(ret, dict) and "blog" in ret:
ret = ret["blog"]
return [
c for c in ret
]
elif not raw_data:
from .comment import Comment
ret = self.steem.rpc.get_blog({'account': account, 'start_entry_id': start_entry_id, 'limit': limit}, api='follow')
if isinstance(ret, dict) and "blog" in ret:
ret = ret["blog"]
return [
Comment(c["comment"], steem_instance=self.steem) for c in ret
]
except:
success = False

if not self.steem.rpc.get_use_appbase() or not success:
if raw_data and short_entries:
return [
c for c in self.steem.rpc.get_blog_entries(account, start_entry_id, limit, api='follow')
]

elif raw_data:
return [
c for c in self.steem.rpc.get_blog(account, start_entry_id, 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, start_entry_id, limit, api='follow')
]

def get_blog_authors(self, account=None):
""" Returns a list of authors that have had their content reblogged on a given blog account
@@ -787,7 +852,10 @@ def get_blog_authors(self, account=None):
raise OfflineHasNoRPCException("No RPC available in offline mode!")
self.steem.rpc.set_next_node_on_empty_reply(False)
if self.steem.rpc.get_use_appbase():
return self.steem.rpc.get_blog_authors({'blog_account': account}, api='follow')['blog_authors']
try:
return self.steem.rpc.get_blog_authors({'blog_account': account}, api='follow')['blog_authors']
except:
return self.steem.rpc.get_blog_authors(account, api='follow')
else:
return self.steem.rpc.get_blog_authors(account, api='follow')

@@ -860,7 +928,7 @@ def _get_followers(self, direction="follower", last_user="", what="blog", limit=
elif direction == "following":
followers = self.steem.rpc.get_following(query, api='follow')
if isinstance(followers, dict) and 'following' in followers:
followers = followers['following']
followers = followers['following']
else:
if direction == "follower":
followers = self.steem.rpc.get_followers(self.name, last_user, what, limit, api='follow')
@@ -985,7 +1053,7 @@ def get_balance(self, balances, symbol):
balances = self.total_balances
else:
return

if isinstance(symbol, dict) and "symbol" in symbol:
symbol = symbol["symbol"]

@@ -1084,14 +1152,17 @@ def get_bandwidth(self):
vesting_shares = self["vesting_shares"].amount
if reserve_ratio is None or reserve_ratio["max_virtual_bandwidth"] is None:
return {"used": None,
"allocated": None}
"allocated": None}
max_virtual_bandwidth = float(reserve_ratio["max_virtual_bandwidth"])
total_vesting_shares = Amount(global_properties["total_vesting_shares"], steem_instance=self.steem).amount
allocated_bandwidth = (max_virtual_bandwidth * (vesting_shares + received_vesting_shares) / total_vesting_shares)
allocated_bandwidth = round(allocated_bandwidth / 1000000)

if not not self.steem.is_connected() and self.steem.rpc.get_use_appbase():
account_bandwidth = self.get_account_bandwidth(bandwidth_type=1, account=account)
if self.steem.is_connected() and self.steem.rpc.get_use_appbase():
try:
account_bandwidth = self.get_account_bandwidth(bandwidth_type=1, account=account)
except:
account_bandwidth = None
if account_bandwidth is None:
return {"used": 0,
"allocated": allocated_bandwidth}
@@ -1439,7 +1510,7 @@ def get_account_votes(self, account=None):
ret = self.steem.rpc.list_votes({"start": [account, start_author, start_permlink], "limit": 1000, "order": "by_voter_comment"}, api="database")["votes"]
if start_author != "":
if len(ret) == 0:
finished = True
finished = True
ret = ret[1:]
for vote in ret:
if vote["voter"] != account:
@@ -2208,6 +2279,30 @@ def update_account_metadata(self, metadata, account=None, **kwargs):
})
return self.steem.finalizeOp(op, account, "active", **kwargs)

def update_account_jsonmetadata(self, metadata, account=None, **kwargs):
""" Update an account's profile in json_metadata using the posting key
:param dict metadata: The new metadata to use
:param str account: (optional) the account to allow access
to (defaults to ``default_account``)
"""
if account is None:
account = self
else:
account = Account(account, steem_instance=self.steem)
if isinstance(metadata, dict):
metadata = json.dumps(metadata)
elif not isinstance(metadata, str):
raise ValueError("Profile must be a dict or string!")
op = operations.Account_update(
**{
"account": account["name"],
"posting_json_metadata": metadata,
"prefix": self.steem.prefix,
})
return self.steem.finalizeOp(op, account, "posting", **kwargs)

# -------------------------------------------------------------------------
# Approval and Disapproval of witnesses
# -------------------------------------------------------------------------
3 changes: 1 addition & 2 deletions beem/amount.py
Original file line number Diff line number Diff line change
@@ -117,8 +117,6 @@ def __init__(self, amount, asset=None, fixed_point_arithmetic=False, new_appbase
self["symbol"] = self["asset"]["symbol"]
self["amount"] = Decimal(amount["amount"]) / Decimal(10 ** self["asset"]["precision"])



elif isinstance(amount, (float)) and asset and isinstance(asset, Asset):
self["amount"] = str(amount)
self["asset"] = asset
@@ -272,6 +270,7 @@ def __mul__(self, other):
def __floordiv__(self, other):
a = self.copy()
if isinstance(other, Amount):
from .price import Price
check_asset(other["asset"], self["asset"])
return Price(self, other, steem_instance=self.steem)
else:
Loading