-
Notifications
You must be signed in to change notification settings - Fork 143
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Represent fungible asset values as a distinct type and support minor units #954
Conversation
afa4a9f
to
2341ba9
Compare
Codecov Report
@@ Coverage Diff @@
## main #954 +/- ##
==========================================
+ Coverage 88.21% 88.34% +0.12%
==========================================
Files 282 284 +2
Lines 25524 26055 +531
==========================================
+ Hits 22516 23018 +502
+ Misses 1535 1528 -7
- Partials 1473 1509 +36
|
99e9b43
to
0da1afc
Compare
/// name="sign"/>, <paramref name="majorUnit"/> and <paramref name="minorUnit"/>. | ||
/// </summary> | ||
/// <param name="currency">The currency to create a value.</param> | ||
/// <param name="sign">Indicates the sign (negative, positive, or zero) of the value. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We may need new enum for this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Avoiding a new enum type was intended, because:
BigInteger.Sign
property does the same thing.- It is much handier than enum values when adding a sign to values, i.e., you can simply do that by
v.Sign * anotherValue
instead ofv.Sign == Sign.Negative ? -anotherValue : anotherValue
.
/// <exception cref="DivideByZeroException">Thrown when the <paramref name="divisor"/> is | ||
/// zero.</exception> | ||
[Pure] | ||
public BigInteger DivRem(FungibleAssetValue divisor, out FungibleAssetValue remainder) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this operation(someFAV.DivRem(someOtherFAV, out FAV rem)
) really needed?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's intended to be parallel with BigInteger
… a overloaded method which returns a remainder through a tuple instead out
parameter does not exist in BigInteger
but I added here for convenience' sake.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was wondering there are situations in which one FAV needs to be divided by another FAV (not a number). I guess we can cover most of cases by .DivRem(BigInteger, out FungibleAssetValue)
.
IEquatable<FungibleAssetValue>, | ||
IComparable<FungibleAssetValue>, | ||
IComparable, | ||
ISerializable |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It would be better if we also adding IForamttable
. (even next PR).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I also wanted to implement IFormattable
in this patch, but its specification seemed quite complex… I am going to implement it next time
(Bencodex.Types.Integer)stateCompleter(blockChain, hash, address, currency); | ||
{ | ||
FungibleAssetValue balance = stateCompleter(blockChain, hash, address, currency); | ||
return (Bencodex.Types.Integer)balance.RawValue; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it okay returning only .RawValue
without currency
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, raw state completer (Func<BlockChain<T>, HashDigest<SHA256>, IValue>
) used by only BlockChain<T>.GetRawState()
method, which is internal
, takes IValue
instead of FungibleAssetValue
.
0da1afc
to
a7f4925
Compare
/// <see cref="FungibleAssetValue.MajorUnit"/>. For more precision, directly use <see | ||
/// cref="FungibleAssetValue"/>'s constructors instead.</remarks> | ||
[Pure] | ||
public static FungibleAssetValue operator *(BigInteger quantity, Currency currency) => |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you please explain why this returns FungibleAssetValue
instead of Currency
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Even though this diverts the multiplying operator (*
), it's not an actual multiplication, but a shortcut for creating a new FungibleAssetValue
: 123 * foo
is equivalent to new FungibleAssetValue(currency: foo, major: 1, minor: 0)
.
This pull request adds
Currency.DecimalPlaces
property andFungibleAssetValue
type to address the issue #944.From this changes, fungible asset values are no more represented as
BigInteger
, which does not hold any decimal places, butFungibleAssetValue
instead. The introducedFungibleAssetValue
type is essentially a pair of(Currency, BigInteger)
. It cannot mix heterogeneous currencies.FungibleAssetValue
s can be made like below:This patch also introduces a new property named
DecimalPlaces
toCurrency
. This defines how precise can currency values be, like 2 decimal places for cents of US Dollar. Continued from the above example, you can represent 123.45 GOLD like below:On the other hand, it does not allow more decimal places than it's specified in
DecimalPlaces
. For example, the following code causesArgumentException
:FungibleAssetValue
type mimics other integral types likeBigInteger
; it provides+
,-
,*
,%
,.DivRem()
,.Abs()
,.Sign
and so on, except for division operator (/
) which is bug-prone IMHO. For the rationale, see also the XML comment onFungibleAssetValue
struct.In order to print the value, simply use
.ToString()
method or if you want only quantity without currency use.GetQuantityString()
method.Besides, this patch adds a new namespace
Libplanet.Assets
andCurrency
is also moved into that.