mirror of
https://github.com/XRPLF/rippled.git
synced 2025-11-20 11:05:54 +00:00
Add DeliverMin transaction field (RIPD-930)
This commit is contained in:
committed by
Vinnie Falco
parent
b7f07aed00
commit
4dc573f195
@@ -1859,6 +1859,10 @@
|
||||
</ClCompile>
|
||||
<ClInclude Include="..\..\src\ripple\app\tx\tests\common_transactor.h">
|
||||
</ClInclude>
|
||||
<ClCompile Include="..\..\src\ripple\app\tx\tests\DeliverMin.test.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\ripple\app\tx\tests\MultiSign.test.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
|
||||
@@ -3435,6 +3439,8 @@
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\ripple\test\jtx\basic_prop.h">
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\ripple\test\jtx\delivermin.h">
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\ripple\test\jtx\Env.h">
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\ripple\test\jtx\fee.h">
|
||||
@@ -3457,6 +3463,10 @@
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\ripple\test\jtx\impl\delivermin.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\ripple\test\jtx\impl\Env.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
|
||||
|
||||
@@ -2592,6 +2592,9 @@
|
||||
<ClInclude Include="..\..\src\ripple\app\tx\tests\common_transactor.h">
|
||||
<Filter>ripple\app\tx\tests</Filter>
|
||||
</ClInclude>
|
||||
<ClCompile Include="..\..\src\ripple\app\tx\tests\DeliverMin.test.cpp">
|
||||
<Filter>ripple\app\tx\tests</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\ripple\app\tx\tests\MultiSign.test.cpp">
|
||||
<Filter>ripple\app\tx\tests</Filter>
|
||||
</ClCompile>
|
||||
@@ -4194,6 +4197,9 @@
|
||||
<ClInclude Include="..\..\src\ripple\test\jtx\basic_prop.h">
|
||||
<Filter>ripple\test\jtx</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\ripple\test\jtx\delivermin.h">
|
||||
<Filter>ripple\test\jtx</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\ripple\test\jtx\Env.h">
|
||||
<Filter>ripple\test\jtx</Filter>
|
||||
</ClInclude>
|
||||
@@ -4215,6 +4221,9 @@
|
||||
<ClCompile Include="..\..\src\ripple\test\jtx\impl\balance.cpp">
|
||||
<Filter>ripple\test\jtx\impl</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\ripple\test\jtx\impl\delivermin.cpp">
|
||||
<Filter>ripple\test\jtx\impl</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\ripple\test\jtx\impl\Env.cpp">
|
||||
<Filter>ripple\test\jtx\impl</Filter>
|
||||
</ClCompile>
|
||||
|
||||
@@ -192,4 +192,11 @@
|
||||
#define RIPPLE_USE_OPENSSL 0
|
||||
#endif
|
||||
|
||||
/** Config: RIPPLE_ENABLE_DELIVERMIN
|
||||
Enables processing of delivermin in transactions
|
||||
*/
|
||||
#ifndef RIPPLE_ENABLE_DELIVERMIN
|
||||
#define RIPPLE_ENABLE_DELIVERMIN 0
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
#include <ripple/app/paths/RippleCalc.h>
|
||||
#include <ripple/basics/Log.h>
|
||||
#include <ripple/protocol/TxFlags.h>
|
||||
#include <ripple/protocol/JsonFields.h>
|
||||
|
||||
namespace ripple {
|
||||
|
||||
@@ -44,6 +45,12 @@ Payment::preCheck ()
|
||||
bool const defaultPathsAllowed = !(uTxFlags & tfNoRippleDirect);
|
||||
bool const bPaths = mTxn.isFieldPresent (sfPaths);
|
||||
bool const bMax = mTxn.isFieldPresent (sfSendMax);
|
||||
bool const deliverMin =
|
||||
#if RIPPLE_ENABLE_DELIVERMIN
|
||||
#else
|
||||
(view().flags() & tapENABLE_TESTING) &&
|
||||
#endif
|
||||
mTxn.isFieldPresent(sfDeliverMin);
|
||||
|
||||
STAmount const saDstAmount (mTxn.getFieldAmount (sfAmount));
|
||||
|
||||
@@ -138,6 +145,45 @@ Payment::preCheck ()
|
||||
"No ripple direct specified for XRP to XRP.";
|
||||
return temBAD_SEND_XRP_NO_DIRECT;
|
||||
}
|
||||
if (deliverMin)
|
||||
{
|
||||
#if ! RIPPLE_ENABLE_DELIVERMIN
|
||||
if (! (view().flags() & tapENABLE_TESTING))
|
||||
return temMALFORMED;
|
||||
#endif
|
||||
|
||||
if (! partialPaymentAllowed)
|
||||
{
|
||||
j_.trace << "Malformed transaction: Partial payment not "
|
||||
"specified for " << jss::DeliverMin.c_str() << ".";
|
||||
return temBAD_AMOUNT;
|
||||
}
|
||||
|
||||
auto const dMin = mTxn.getFieldAmount(sfDeliverMin);
|
||||
if (!isLegalNet(dMin) || dMin <= zero)
|
||||
{
|
||||
j_.trace << "Malformed transaction: Invalid " <<
|
||||
jss::DeliverMin.c_str() << " amount. " <<
|
||||
dMin.getFullText();
|
||||
return temBAD_AMOUNT;
|
||||
}
|
||||
if (dMin.issue() != saDstAmount.issue())
|
||||
{
|
||||
j_.trace << "Malformed transaction: Dst issue differs "
|
||||
"from " << jss::DeliverMin.c_str() << ". " <<
|
||||
dMin.getFullText();
|
||||
return temBAD_AMOUNT;
|
||||
}
|
||||
if (bMax &&
|
||||
(dMin.getCurrency() == maxSourceAmount.getCurrency() &&
|
||||
dMin > maxSourceAmount))
|
||||
{
|
||||
j_.trace << "Malformed transaction: SendMax less than " <<
|
||||
jss::DeliverMin.c_str() << ". " <<
|
||||
dMin.getFullText();
|
||||
return temBAD_AMOUNT;
|
||||
}
|
||||
}
|
||||
|
||||
return Transactor::preCheck ();
|
||||
}
|
||||
@@ -152,6 +198,13 @@ Payment::doApply ()
|
||||
bool const defaultPathsAllowed = !(uTxFlags & tfNoRippleDirect);
|
||||
bool const bPaths = mTxn.isFieldPresent (sfPaths);
|
||||
bool const bMax = mTxn.isFieldPresent (sfSendMax);
|
||||
bool const deliverMin =
|
||||
#if RIPPLE_ENABLE_DELIVERMIN
|
||||
#else
|
||||
(view().flags() & tapENABLE_TESTING) &&
|
||||
#endif
|
||||
mTxn.isFieldPresent(sfDeliverMin);
|
||||
|
||||
AccountID const uDstAccountID (mTxn.getAccountID (sfDestination));
|
||||
STAmount const saDstAmount (mTxn.getFieldAmount (sfAmount));
|
||||
STAmount maxSourceAmount;
|
||||
@@ -291,8 +344,15 @@ Payment::doApply ()
|
||||
|
||||
// TODO: is this right? If the amount is the correct amount, was
|
||||
// the delivered amount previously set?
|
||||
if (rc.result () == tesSUCCESS && rc.actualAmountOut != saDstAmount)
|
||||
ctx_.deliverAmount (rc.actualAmountOut);
|
||||
if (rc.result () == tesSUCCESS &&
|
||||
rc.actualAmountOut != saDstAmount)
|
||||
{
|
||||
if (deliverMin && rc.actualAmountOut <
|
||||
mTxn.getFieldAmount (sfDeliverMin))
|
||||
rc.setResult (tecPATH_PARTIAL);
|
||||
else
|
||||
ctx_.deliverAmount (rc.actualAmountOut);
|
||||
}
|
||||
|
||||
terResult = rc.result ();
|
||||
}
|
||||
|
||||
129
src/ripple/app/tx/tests/DeliverMin.test.cpp
Normal file
129
src/ripple/app/tx/tests/DeliverMin.test.cpp
Normal file
@@ -0,0 +1,129 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of rippled: https://github.com/ripple/rippled
|
||||
Copyright (c) 2012-2015 Ripple Labs Inc.
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#include <BeastConfig.h>
|
||||
#include <ripple/test/jtx.h>
|
||||
#include <beast/unit_test/suite.h>
|
||||
|
||||
namespace ripple {
|
||||
namespace test {
|
||||
|
||||
class DeliverMin_test : public beast::unit_test::suite
|
||||
{
|
||||
public:
|
||||
void
|
||||
test_convert_all_of_an_asset()
|
||||
{
|
||||
testcase("Convert all of an asset using DeliverMin");
|
||||
|
||||
using namespace jtx;
|
||||
auto const gw = Account("gateway");
|
||||
auto const USD = gw["USD"];
|
||||
|
||||
{
|
||||
Env env(*this);
|
||||
env.fund(XRP(10000), "alice", "bob", "carol", gw);
|
||||
env.trust(USD(100), "alice", "bob", "carol");
|
||||
env(pay("alice", "bob", USD(10)), delivermin(USD(10)), ter(temBAD_AMOUNT));
|
||||
env(pay("alice", "bob", USD(10)), delivermin(USD(-5)),
|
||||
txflags(tfPartialPayment), ter(temBAD_AMOUNT));
|
||||
env(pay("alice", "bob", USD(10)), delivermin(XRP(5)),
|
||||
txflags(tfPartialPayment), ter(temBAD_AMOUNT));
|
||||
env(pay("alice", "bob", USD(10)),
|
||||
delivermin(Account("carol")["USD"](5)),
|
||||
txflags(tfPartialPayment), ter(temBAD_AMOUNT));
|
||||
env(pay("alice", "bob", USD(10)), delivermin(USD(15)),
|
||||
txflags(tfPartialPayment), ter(tecPATH_DRY));
|
||||
env(pay("alice", "bob", USD(10)),
|
||||
delivermin(USD(10)), txflags(tfPartialPayment),
|
||||
sendmax(USD(9)), ter(temBAD_AMOUNT));
|
||||
env(pay(gw, "carol", USD(50)));
|
||||
env(offer("carol", XRP(5), USD(5)));
|
||||
env(pay("alice", "bob", USD(10)), paths(XRP),
|
||||
delivermin(USD(7)), txflags(tfPartialPayment),
|
||||
sendmax(XRP(20)), ter(tecPATH_PARTIAL));
|
||||
env.require(balance("alice", XRP(9999.99998)));
|
||||
env.require(balance("bob", XRP(10000)));
|
||||
|
||||
// DeliverMin greater than destination amount
|
||||
env(pay("alice", "bob", USD(5)), paths(XRP),
|
||||
delivermin(USD(50)), txflags(tfPartialPayment),
|
||||
sendmax(XRP(5)));
|
||||
env.require(balance("bob", USD(5)));
|
||||
}
|
||||
|
||||
{
|
||||
Env env(*this);
|
||||
env.fund(XRP(10000), "alice", "bob", gw);
|
||||
env.trust(USD(1000), "alice", "bob");
|
||||
env(pay(gw, "bob", USD(100)));
|
||||
env(offer("bob", XRP(100), USD(100)));
|
||||
env(pay("alice", "alice", USD(10000)), paths(XRP),
|
||||
delivermin(USD(100)), txflags(tfPartialPayment),
|
||||
sendmax(XRP(100)));
|
||||
env.require(balance("alice", USD(100)));
|
||||
}
|
||||
|
||||
{
|
||||
Env env(*this);
|
||||
env.fund(XRP(10000), "alice", "bob", "carol", gw);
|
||||
env.trust(USD(1000), "bob", "carol");
|
||||
env(pay(gw, "bob", USD(200)));
|
||||
env(offer("bob", XRP(100), USD(100)));
|
||||
env(offer("bob", XRP(1000), USD(100)));
|
||||
env(offer("bob", XRP(10000), USD(100)));
|
||||
env(pay("alice", "carol", USD(10000)), paths(XRP),
|
||||
delivermin(USD(200)), txflags(tfPartialPayment),
|
||||
sendmax(XRP(1000)), ter(tecPATH_PARTIAL));
|
||||
env(pay("alice", "carol", USD(10000)), paths(XRP),
|
||||
delivermin(USD(200)), txflags(tfPartialPayment),
|
||||
sendmax(XRP(1100)));
|
||||
env.require(balance("bob", USD(0)));
|
||||
env.require(balance("carol", USD(200)));
|
||||
}
|
||||
|
||||
{
|
||||
Env env(*this);
|
||||
env.fund(XRP(10000), "alice", "bob", "carol", "dan", gw);
|
||||
env.trust(USD(1000), "bob", "carol", "dan");
|
||||
env(pay(gw, "bob", USD(100)));
|
||||
env(pay(gw, "dan", USD(100)));
|
||||
env(offer("bob", XRP(100), USD(100)));
|
||||
env(offer("bob", XRP(1000), USD(100)));
|
||||
env(offer("dan", XRP(100), USD(100)));
|
||||
env(pay("alice", "carol", USD(10000)), paths(XRP),
|
||||
delivermin(USD(200)), txflags(tfPartialPayment),
|
||||
sendmax(XRP(200)));
|
||||
env.require(balance("bob", USD(0)));
|
||||
env.require(balance("carol", USD(200)));
|
||||
env.require(balance("dan", USD(0)));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
run()
|
||||
{
|
||||
test_convert_all_of_an_asset();
|
||||
}
|
||||
};
|
||||
|
||||
BEAST_DEFINE_TESTSUITE(DeliverMin,app,ripple)
|
||||
|
||||
} // test
|
||||
} // ripple
|
||||
@@ -39,6 +39,7 @@ JSS ( Account ); // in: TransactionSign; field.
|
||||
JSS ( Amount ); // in: TransactionSign; field.
|
||||
JSS ( ClearFlag ); // field.
|
||||
JSS ( Destination ); // in: TransactionSign; field.
|
||||
JSS ( DeliverMin ); // in: TransactionSign
|
||||
JSS ( Fee ); // in/out: TransactionSign; field.
|
||||
JSS ( Flags ); // in/out: TransactionSign; field.
|
||||
JSS ( Invalid ); //
|
||||
|
||||
@@ -381,6 +381,7 @@ extern SField const sfLowLimit;
|
||||
extern SField const sfHighLimit;
|
||||
extern SField const sfFee;
|
||||
extern SField const sfSendMax;
|
||||
extern SField const sfDeliverMin;
|
||||
|
||||
// currency amount (uncommon)
|
||||
extern SField const sfMinimumOffer;
|
||||
|
||||
@@ -160,15 +160,16 @@ SField const sfTakerGetsCurrency = make::one(&sfTakerGetsCurrency, STI_HASH160,
|
||||
SField const sfTakerGetsIssuer = make::one(&sfTakerGetsIssuer, STI_HASH160, 4, "TakerGetsIssuer");
|
||||
|
||||
// currency amount (common)
|
||||
SField const sfAmount = make::one(&sfAmount, STI_AMOUNT, 1, "Amount");
|
||||
SField const sfBalance = make::one(&sfBalance, STI_AMOUNT, 2, "Balance");
|
||||
SField const sfLimitAmount = make::one(&sfLimitAmount, STI_AMOUNT, 3, "LimitAmount");
|
||||
SField const sfTakerPays = make::one(&sfTakerPays, STI_AMOUNT, 4, "TakerPays");
|
||||
SField const sfTakerGets = make::one(&sfTakerGets, STI_AMOUNT, 5, "TakerGets");
|
||||
SField const sfLowLimit = make::one(&sfLowLimit, STI_AMOUNT, 6, "LowLimit");
|
||||
SField const sfHighLimit = make::one(&sfHighLimit, STI_AMOUNT, 7, "HighLimit");
|
||||
SField const sfFee = make::one(&sfFee, STI_AMOUNT, 8, "Fee");
|
||||
SField const sfSendMax = make::one(&sfSendMax, STI_AMOUNT, 9, "SendMax");
|
||||
SField const sfAmount = make::one(&sfAmount, STI_AMOUNT, 1, "Amount");
|
||||
SField const sfBalance = make::one(&sfBalance, STI_AMOUNT, 2, "Balance");
|
||||
SField const sfLimitAmount = make::one(&sfLimitAmount, STI_AMOUNT, 3, "LimitAmount");
|
||||
SField const sfTakerPays = make::one(&sfTakerPays, STI_AMOUNT, 4, "TakerPays");
|
||||
SField const sfTakerGets = make::one(&sfTakerGets, STI_AMOUNT, 5, "TakerGets");
|
||||
SField const sfLowLimit = make::one(&sfLowLimit, STI_AMOUNT, 6, "LowLimit");
|
||||
SField const sfHighLimit = make::one(&sfHighLimit, STI_AMOUNT, 7, "HighLimit");
|
||||
SField const sfFee = make::one(&sfFee, STI_AMOUNT, 8, "Fee");
|
||||
SField const sfSendMax = make::one(&sfSendMax, STI_AMOUNT, 9, "SendMax");
|
||||
SField const sfDeliverMin = make::one(&sfDeliverMin, STI_AMOUNT, 10, "DeliverMin");
|
||||
|
||||
// currency amount (uncommon)
|
||||
SField const sfMinimumOffer = make::one(&sfMinimumOffer, STI_AMOUNT, 16, "MinimumOffer");
|
||||
|
||||
@@ -64,6 +64,7 @@ TxFormats::TxFormats ()
|
||||
<< SOElement (sfPaths, SOE_DEFAULT)
|
||||
<< SOElement (sfInvoiceID, SOE_OPTIONAL)
|
||||
<< SOElement (sfDestinationTag, SOE_OPTIONAL)
|
||||
<< SOElement (sfDeliverMin, SOE_OPTIONAL)
|
||||
;
|
||||
|
||||
add ("EnableAmendment", ttAMENDMENT)
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
#include <ripple/test/jtx/advance.h>
|
||||
#include <ripple/test/jtx/amount.h>
|
||||
#include <ripple/test/jtx/balance.h>
|
||||
#include <ripple/test/jtx/delivermin.h>
|
||||
#include <ripple/test/jtx/Env.h>
|
||||
#include <ripple/test/jtx/fee.h>
|
||||
#include <ripple/test/jtx/flags.h>
|
||||
|
||||
@@ -172,7 +172,7 @@ struct XRP_t
|
||||
std::int64_t, std::uint64_t>{v} *
|
||||
dropsPerXRP<T>::value };
|
||||
}
|
||||
|
||||
|
||||
PrettyAmount
|
||||
operator()(double v) const
|
||||
{
|
||||
|
||||
50
src/ripple/test/jtx/delivermin.h
Normal file
50
src/ripple/test/jtx/delivermin.h
Normal file
@@ -0,0 +1,50 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of rippled: https://github.com/ripple/rippled
|
||||
Copyright (c) 2012, 2013 Ripple Labs Inc.
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef RIPPLE_TEST_JTX_DELIVERMIN_H_INCLUDED
|
||||
#define RIPPLE_TEST_JTX_DELIVERMIN_H_INCLUDED
|
||||
|
||||
#include <ripple/test/jtx/Env.h>
|
||||
#include <ripple/protocol/STAmount.h>
|
||||
|
||||
namespace ripple {
|
||||
namespace test {
|
||||
namespace jtx {
|
||||
|
||||
/** Sets the DeliverMin on a JTx. */
|
||||
class delivermin
|
||||
{
|
||||
private:
|
||||
STAmount amount_;
|
||||
|
||||
public:
|
||||
delivermin (STAmount const& amount)
|
||||
: amount_(amount)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
operator()(Env const&, JTx& jtx) const;
|
||||
};
|
||||
|
||||
} // jtx
|
||||
} // test
|
||||
} // ripple
|
||||
|
||||
#endif
|
||||
@@ -52,6 +52,24 @@ PrettyAmount::operator AnyAmount() const
|
||||
return { amount_ };
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static
|
||||
std::string
|
||||
to_places(const T d, std::uint8_t places)
|
||||
{
|
||||
assert(places <= std::numeric_limits<T>::digits10);
|
||||
|
||||
std::ostringstream oss;
|
||||
oss << std::setprecision(places) << std::fixed << d;
|
||||
|
||||
std::string out = oss.str();
|
||||
out.erase(out.find_last_not_of('0') + 1, std::string::npos);
|
||||
if (out.back() == '.')
|
||||
out.pop_back();
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
std::ostream&
|
||||
operator<< (std::ostream& os,
|
||||
PrettyAmount const& amount)
|
||||
@@ -72,11 +90,10 @@ operator<< (std::ostream& os,
|
||||
}
|
||||
auto const d = double(n) /
|
||||
dropsPerXRP<int>::value;
|
||||
os.precision(6);
|
||||
if (amount.value().negative())
|
||||
os << "-" << d << " XRP";
|
||||
else
|
||||
os << d << " XRP";
|
||||
os << "-";
|
||||
|
||||
os << to_places(d, 6) << " XRP";
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
36
src/ripple/test/jtx/impl/delivermin.cpp
Normal file
36
src/ripple/test/jtx/impl/delivermin.cpp
Normal file
@@ -0,0 +1,36 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of rippled: https://github.com/ripple/rippled
|
||||
Copyright (c) 2012, 2013 Ripple Labs Inc.
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#include <BeastConfig.h>
|
||||
#include <ripple/test/jtx/delivermin.h>
|
||||
#include <ripple/protocol/JsonFields.h>
|
||||
|
||||
namespace ripple {
|
||||
namespace test {
|
||||
namespace jtx {
|
||||
|
||||
void
|
||||
delivermin::operator()(Env const& env, JTx& jt) const
|
||||
{
|
||||
jt.jv[jss::DeliverMin] = amount_.getJson(0);
|
||||
}
|
||||
|
||||
} // jtx
|
||||
} // test
|
||||
} // ripple
|
||||
@@ -47,3 +47,4 @@
|
||||
#include <ripple/app/tx/tests/OfferStream.test.cpp>
|
||||
#include <ripple/app/tx/tests/Offer.test.cpp>
|
||||
#include <ripple/app/tx/tests/Taker.test.cpp>
|
||||
#include <ripple/app/tx/tests/DeliverMin.test.cpp>
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#include <ripple/test/jtx/impl/advance.cpp>
|
||||
#include <ripple/test/jtx/impl/amount.cpp>
|
||||
#include <ripple/test/jtx/impl/balance.cpp>
|
||||
#include <ripple/test/jtx/impl/delivermin.cpp>
|
||||
#include <ripple/test/jtx/impl/Env.cpp>
|
||||
#include <ripple/test/jtx/impl/fee.cpp>
|
||||
#include <ripple/test/jtx/impl/flags.cpp>
|
||||
|
||||
Reference in New Issue
Block a user