-
Notifications
You must be signed in to change notification settings - Fork 124
Add unit converter for transaction values #18
Comments
@todofixthis I am looking forward to work on this bug. def convert_value_to_standard_system_units(value):
# type: string -> float
"""
Return a floating point value in Standard System of Units from string
'i' : 1,
'Ki' : 1000,
'Mi' : 1000000,
'Gi' : 1000000000,
'Ti' : 1000000000000,
'Pi' : 1000000000000000
"""
value_tuple = value.split()
unit = 0
if(value_tuple[1] == "i"):
unit = 1
elif(value_tuple[1] == "Ki"):
unit = 1000
elif(value_tuple[1] == "Mi"):
unit = 1000000
elif(value_tuple[1] == "Gi"):
unit = 1000000000
elif(value_tuple[1] == "Ti"):
unit = 1000000000000
elif(value_tuple[1] == "Pi"):
unit = 1000000000000000
return float(value_tuple[0])*unit Is this the correct approach? |
Hey @jinankjain. The approach you've laid out looks good. I think it could be improved with some validation ( Looking forward to your pull request (: |
Hi! I've had a crack at it. def convert_value_to_standard_system_units(value):
# type: string -> float
"""
Return a floating point value in Standard System of Units from string
"""
standard_units = {
'i': 1,
'Ki': 1000,
'Mi': 1000000,
'Gi': 1000000000,
'Ti': 1000000000000,
'Pi': 1000000000000000
}
default_unit_prefix = 'i'
# Check value type
if type(value) != str:
print("[ERROR] Input(%s) is not valid." % type(value))
return False
value_tuple = value.split()
# Check if input amount is valid
try:
value = float(value_tuple[0])
except (ValueError, IndexError) as e:
print("[ERROR] (%s) Invalid amount received: %s" % (e, value))
return False
# Check prefix and set unit value. If no prefix or prefix invalid, set to default. (Could cause problems?)
try:
unit_prefix = value_tuple[1]
unit_value = standard_units[unit_prefix]
except (IndexError, KeyError) as e:
print("[WARNING] (%s) Invalid unit prefix given. Using default '%s'." % (e, default_unit_prefix))
unit_value = standard_units[default_unit_prefix]
return value * unit_value
########################
####### T E S T ########
########################
if __name__ == '__main__':
print("Input value: '25.8 Ji'")
print("Return value: {}\n\n".format(convert_value_to_standard_system_units('25.8 Ji')))
print("Input value: ''")
print("Return value: {}\n\n".format(convert_value_to_standard_system_units('')))
print("Input value: '25.8 Ti'")
print("Return value: {}\n\n".format(convert_value_to_standard_system_units('25.8 Ti')))
print("Input value: '25.8 Pi'")
print("Return value: {}\n\n".format(convert_value_to_standard_system_units('25.8 Pi')))
print("Input value: '25.8 i'")
print("Return value: {}\n\n".format(convert_value_to_standard_system_units('25.8 i')))
print("Input value: '25.8Mi'")
print("Return value: {}\n\n".format(convert_value_to_standard_system_units('25.8Mi')))
print("Input value: 25.8 (float)")
print("Return value: {}".format(convert_value_to_standard_system_units(25.8))) TEST OUTPUT:
|
@vynes The main problem that I was facing was trying to integrate this conversion function into the system it caused a lot of error as I have to rewrite all the test. |
@jinankjain @vynes Thanks for jumping on this! Let me know if you have any questions or need assistance integrating it into the codebase. You can also find me on the IOTA slack (drop by the |
Am I right in saying that this should return int (not float), since iota (i) is the smallest unit? |
Interesting question! I think returning a float makes the most sense in this case:
Now, it's true that if the caller actually doesn't want a float value, we are putting the burden on the caller to validate the result... but odds are good that the caller will have to perform that validation anyway. Here's an example: def create_txn(address, value):
# type: (Address, Union[Text, int]) -> ProposedTransaction
# If ``value`` is a formatted string, convert it into an integer amount.
if isinstance(value, string_types):
value = convert_units(value, 'i')
# By this point, ``value`` must be an integer.
# Either an integer was passed into the function,
# or ``convert_units`` converted it into an int.
if not isinstance(value, int):
raise TypeError('``value`` must be an integer!')
... In this example, By allowing the |
Okay, that makes sense, thanks. I guess I was under the impression that IOTAs are not divisible. |
You are correct that IOTAs are not divisible, according to the IOTA protocol. However, there may be cases where an application might use fractional IOTAs internally (e.g., exchanges, computing interest/dividends, smart contracts, etc.). In order to use those IOTAs in a transaction, it will have to convert the value into an integer, but until that point, it can do whatever it wants (: |
Sorry to be a pain, but I think I might have misunderstood the context in which this converter will function.
Does that mean that this will only serve as a helper function which the application may or may not want to use? And not by the pyota lib receiving values from the application in the form of |
No worries. I'd like this to be integrated into PyOTA, but it should also exist as its own thing, so that application developers can take advantage of it, too. E.g., developers should be able to do something like this: iota.send_transfer([ProposedTransaction(..., value='1.2 Mi'), ...], ...) However, I think it should be up to E.g., if an application developer wants to do something like this: iotas = convert_units('1.2345 Ki', 'i')
do_something_with(iotas) We should also support that use case. |
Good, makes sense. Please have a look at: develop...vynes:unit_converter Since the function needs to be accessible from both the api and also internally, I wasn't entirely sure where it should live. It is now just a standalone function inside of I also thought of creating a IotaUnit type, but seemed a bit overkill for such simple thing. The unit map (dict), I put in And then also created a test which ran without error. Let me know what you think. |
Great, thanks @curVV ! I went ahead and created the pull request so that I could leave some comments: Overall, it looks really good; the |
Scheduled for release: 1.2.0 |
[iotaledger#18] Add unit converter
IOTA utilizes the Standard system of Units. See below for all available units:
Add support for specifying units in transactions. E.g.:
The text was updated successfully, but these errors were encountered: