update for beem - amount in the Amount class is a Decimal instead of a float and bug-fix for account.get_balance()

in #utopian-io5 years ago (edited)

Repository

https://github.com/holgern/beem


beem-logo

beem is a python library for steem. beem has now 495 unit tests and a coverage of 70 %. The current version is 0.20.20.
I created a discord channel for answering a question or discussing beem: https://discord.gg/4HM592V
The newest beem version can be installed by:

pip install -U beem

or when using conda:

conda install beem

beem can be updated by:

conda update beem

New Features

The amount in the Amount class is stored as Decimal and not as float anymore

The amount in the Amount class is now stored as Decimal object:

from beem.amount import Amount
a = Amount("6.104 STEEM")
a
6.104 STEEM
a.amount
Decimal('6.104')

For compatibility reasons, I have decided to keep the floating point arithmetic. For example, when I have 6.104 and I want to sent 1/6 out to the six different people, I should have a reminder of 0.002 in my wallet, as 6.102 is nearest number which is dividable through 6 without reminder.

a = Amount("6.104 STEEM")
send_amount = a / 6
print(send_amount)
for i in range(6):
    a -=  send_amount
print(a)

results in

1.017 STEEM
0.000 STEEM

Seems that we have lost 0.002 STEEM. The reason is that the send_amount has a higher precision that the allowed one.

send_amount.amount
Decimal('1.017333333333333333333333333')

Fixed-point arithmetic

In order to fix this, I added a new option fixed_point_arithmetic, when set to True, the amount is rounded down after each operation to the allowed precision.

a = Amount("6.104 STEEM", fixed_point_arithmetic = True)
send_amount = a / 6
print(send_amount)
for i in range(6):
    a -=  send_amount
print(a)

results in

1.017 STEEM
0.002 STEEM

This time, we do not lost the 0.002 STEEM, as the amount in send_amount is rounded:

send_amount.amount
Decimal('1.017')

But the following calculation may not lead to the expected results:

a
0.002 STEEM
(a / 1000) * 1000
0.000 STEEM

Fixed-point arithmetic combined with Floating-point arithmetic

It is also possible to combine both. In the following example, an object keeps its unlimited precision and works with floating-point arithmetic. The send_amount object is rounded down to the precision of 3.

a = Amount("6.104 STEEM")
send_amount = Amount(a / 6, fixed_point_arithmetic=True)
print(send_amount)
for i in range(6):
    a -=  send_amount
print(a)

results in

1.017 STEEM
0.002 STEEM

We were able to achieve the wanted results. In the same time, calculation as the following are still possible:

(a / 1000) * 1000
0.002 STEEM

Casting to float, str and integer

It is possible to cast a Amount object to a float, in this case the amount is not rounded down:

float(Amount("1.999 STEEM") / 2)
0.9995

During casting the object to an integer, it is rounded down to the defined precision:

int(Amount("1.999 STEEM") / 2)
999

The integer is used, when casting the amount object to a dict, which can be used for broadcasting using the appbase format:

(Amount("1.999 STEEM") / 2).json()
{'amount': '999', 'nai': '@@000000021', 'precision': 3}

It is also possible to cast the amount object to a string:

str(Amount("1.999 STEEM") / 2)
'0.999 STEEM'

In both casting functions, the new quantize function is used:

def quantize(amount, precision):
    # make sure amount is decimal and has the asset precision
    amount = Decimal(amount)
    places = Decimal(10) ** (-precision)
    return amount.quantize(places, rounding=ROUND_DOWN)  

The quantize grantees that casting an amount to a string and to an integer returns the same results.

Bug fixes

one-time private key on beempy

I implemented the first part of the suggestion from @blockchainstudio (post where he suggested that a key should be entered when it is not stored in the wallet.

I modified the unlock_wallet function and changed the wallet password promt as follow:

password = click.prompt("Password to unlock wallet or posting/active wif", confirmation_prompt=False, hide_input=True)
try:
    stm.wallet.unlock(password)
except:
    try:
        stm.wallet.setKeys([password])
        print("Wif accepted!")
        return True                
    except:
        raise exceptions.WrongMasterPasswordException("entered password is not a valid password/wif")

These changes allow it now to broadcast a operation as a transfer from an account by entering not the wallet key but the active key. This active key is temporary stored in RAM and deleted afterwards.

Fix issue #171 - Account.get_balance function shows summed value of liquid balance and unclaimed reward

The bug described here has been fixed. Calling the total_balances property had modified also the balances in the account object when either saving balance or reward balance was not empty. The reason was the usage of +=
which had modify the object itself. By replacing the used += by a = which can be seen here:
image.png

and by using a copy of the balance objects, this bug could be fixed:

@property
def available_balances(self):
    """ List balances of an account. This call returns instances of
        :class:`beem.amount.Amount`.
    """
    amount_list = ["balance", "sbd_balance", "vesting_shares"]
    available_amount = []
    for amount in amount_list:
        if amount in self:
            available_amount.append(self[amount].copy())
    return available_amount

Commits

Make a copy of balance objects

Make return argument in generator function compatible to python 2.7

Fix cli unit test

Convert Decimal to float in pricehistory

Fix unit test for the amount class

Fix issue #171 - Account.get_balance function shows summed value of liquid balance and unclaimed reward

Add option to use fixed-point arithmetic on the Amount class

  • commit 15aff5f
  • When fixed_point_arithmetic is set to True, is the amount parameter always be rounded down to the asset precision
  • Add Handling of multiplying with a Price object
  • Both parameter are rounded down to the precision in all comparison operation as ==,

Cast amount to float for calculations

Use decimal for amount in the Amount class

  • commit bde5380
  • change the internal representation of amount from float to Decimal
  • Round amount down to precision
  • Adapt amount test to Decimal
  • Round down all other number in all operatio

Improve all generator functions in account

  • commit 13424bd
  • set num_retries to a default of 100, in order to prevent crashing when a wrong node is set

Fix issue #162 - one-time use private key can be entered instead of unlocking the wallet

  • commit 4a85f37
  • prepare next beem release and increase version number
  • switch default chain to STEEMAPPBASE

Github account

https://github.com/holgern

Sort:  

Good write-up on fixed-point/floating point arithmetics. :) I had a similar problem on sponsor payments at dPoll.

The update is well-covered and includes good examples. The Changelog is clear. Keep it up! :)


Your contribution has been evaluated according to Utopian policies and guidelines, as well as a predefined set of questions pertaining to the category.

To view those questions and the relevant answers related to your post, click here.


Need help? Chat with us on Discord.

[utopian-moderator]

Thank you for your review, @emrebeyler! Keep up the good work!


Everything is okay! 👌


You received an automatic upvote, because I believe in you and I love what you create! 😉

A huge hug from @amico! 🤗

😍 I love promoting @steembasicincome, even with #sbi-skip! 😜


If you dislike this automatic message, please let me know: thanks! 🙏

Thank you so much for participating in the Partiko Delegation Plan Round 1! We really appreciate your support! As part of the delegation benefits, we just gave you a 3.00% upvote! Together, let’s change the world!

This post has been just added as new item to timeline of beem on Steem Projects.

If you want to be notified about new updates from this project, register on Steem Projects and add beem to your favorite projects.

Hi, @holger80!

You just got a 3.23% upvote from SteemPlus!
To get higher upvotes, earn more SteemPlus Points (SPP). On your Steemit wallet, check your SPP balance and click on "How to earn SPP?" to find out all the ways to earn.
If you're not using SteemPlus yet, please check our last posts in here to see the many ways in which SteemPlus can improve your Steem experience on Steemit and Busy.

Thank you for implementing one-time use private key and mentioning me! Also thanks for merging the typo-fix :)

Hi @holger80!

Your post was upvoted by @steem-ua, new Steem dApp, using UserAuthority for algorithmic post curation!
Your post is eligible for our upvote, thanks to our collaboration with @utopian-io!
Feel free to join our @steem-ua Discord server

Hey, @holger80!

Thanks for contributing on Utopian.
We’re already looking forward to your next contribution!

Get higher incentives and support Utopian.io!
Simply set @utopian.pay as a 5% (or higher) payout beneficiary on your contribution post (via SteemPlus or Steeditor).

Want to chat? Join us on Discord https://discord.gg/h52nFrV.

Vote for Utopian Witness!