Skip to content

Commit 32fc34b

Browse files
Merge pull request #17 from CodaProtocol/feature/random-currency
Add Currency.random() function
2 parents e94ed9d + 50e9f17 commit 32fc34b

2 files changed

Lines changed: 64 additions & 0 deletions

File tree

CodaClient.py

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#!/usr/bin/python3
22

3+
import random
34
import requests
45
import time
56
import json
@@ -9,13 +10,27 @@
910
from enum import Enum
1011

1112
class CurrencyFormat(Enum):
13+
"""An Enum representing different formats of Currency in coda.
14+
15+
Constants:
16+
WHOLE - represents whole coda (1 whole coda == 10^9 nanocodas)
17+
NANO - represents the atomic unit of coda
18+
"""
1219
WHOLE = 1
1320
NANO = 2
1421

1522
class CurrencyUnderflow(Exception):
1623
pass
1724

1825
class Currency():
26+
"""A convenience wrapper around interacting with coda currency values.
27+
28+
This class supports performing math on Currency values of differing formats.
29+
Currency instances can be added or subtracted. Currency instances can also be
30+
scaled through multiplication (either against another Currency instance or a
31+
int scalar).
32+
"""
33+
1934
@classmethod
2035
def __nanocodas_from_int(_cls, n):
2136
return n * 1000000000
@@ -32,7 +47,40 @@ def __nanocodas_from_string(_cls, s):
3247
else:
3348
raise Exception('invalid coda currency format: %s' % s)
3449

50+
@classmethod
51+
def random(_cls, lower_bound, upper_bound):
52+
"""Generates a random Currency instance between a provided lower_bound and upper_bound
53+
54+
Arguments:
55+
lower_bound {Currency} -- A Currency instance representing the lower bound for the randomly generated value
56+
upper_bound {Currency} -- A Currency instance representing the upper bound for the randomly generated value
57+
58+
Returns:
59+
Currency - A randomly generated Currency instance between the lower_bound and upper_bound
60+
"""
61+
if not (isinstance(lower_bound, Currency) and isinstance(upper_bound, Currency)):
62+
raise Exception('invalid call to Currency.random: lower and upper bound must be instances of Currency')
63+
if not upper_bound.nanocodas() >= lower_bound.nanocodas():
64+
raise Exception('invalid call to Currency.random: upper_bound is not greater than lower_bound')
65+
if lower_bound == upper_bound:
66+
return lower_bound
67+
bound_range = upper_bound.nanocodas() - lower_bound.nanocodas()
68+
delta = random.randint(0, bound_range)
69+
return lower_bound + Currency(delta, format=CurrencyFormat.NANO)
70+
3571
def __init__(self, value, format=CurrencyFormat.WHOLE):
72+
"""Constructs a new Currency instance. Values of different CurrencyFormats may be passed in to construct the instance.
73+
74+
Arguments:
75+
value {int|float|string} - The value to construct the Currency instance from
76+
format {CurrencyFormat} - The representation format of the value
77+
78+
Return:
79+
Currency - The newly constructed Currency instance
80+
81+
In the case of format=CurrencyFormat.WHOLE, then it is interpreted as value * 10^9 nanocodas.
82+
In the case of format=CurrencyFormat.NANO, value is only allowed to be an int, as there can be no decimal point for nanocodas.
83+
"""
3684
if format == CurrencyFormat.WHOLE:
3785
if isinstance(value, int):
3886
self.__nanocodas = Currency.__nanocodas_from_int(value)
@@ -51,13 +99,23 @@ def __init__(self, value, format=CurrencyFormat.WHOLE):
5199
raise Exception('invalid Currency format %s' % format)
52100

53101
def decimal_format(self):
102+
"""Computes the string decimal format representation of a Currency instance.
103+
104+
Return:
105+
str - The decimal format representation of the Currency instance
106+
"""
54107
s = str(self.__nanocodas)
55108
if len(s) > 9:
56109
return s[:-9] + '.' + s[-9:]
57110
else:
58111
return '0.' + ('0' * (9 - len(s))) + s
59112

60113
def nanocodas(self):
114+
"""Accesses the raw nanocodas representation of a Currency instance.
115+
116+
Return:
117+
int - The nanocodas of the Currency instance represented as an integer
118+
"""
61119
return self.__nanocodas
62120

63121
def __str__(self):

tests/test_currency.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,3 +38,9 @@ def test_mul_int():
3838

3939
def test_mul_currency():
4040
assert (Currency(5) * Currency(2, format=CurrencyFormat.NANO)).nanocodas() == 10 * precision
41+
42+
def test_random():
43+
assert (Currency.random(Currency(5), Currency(5)).nanocodas() == 5 * precision)
44+
for _ in range(25):
45+
rand = Currency.random(Currency(3, format=CurrencyFormat.NANO), Currency(5, format=CurrencyFormat.NANO))
46+
assert (3 <= rand.nanocodas () and rand.nanocodas() <= 5)

0 commit comments

Comments
 (0)